1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: Implements OGRPGDumpDataSource class.
5 * Author: Even Rouault, <even dot rouault at spatialys.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
new() -> Self17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include <cstring>
30 #include "ogr_pgdump.h"
31 #include "cpl_conv.h"
32 #include "cpl_string.h"
33
34 CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 379fc8667418dc54e864d828ea35be513e69abc9 2021-04-03 21:58:21 +0200 Even Rouault $")
35
36 /************************************************************************/
37 /* OGRPGDumpDataSource() */
38 /************************************************************************/
39
40 OGRPGDumpDataSource::OGRPGDumpDataSource( const char* pszNameIn,
41 char** papszOptions ) :
42 pszName(CPLStrdup(pszNameIn))
43 {
44 const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
45
46 bool bUseCRLF = false;
47 if( pszCRLFFormat == nullptr )
48 {
49 #ifdef WIN32
50 bUseCRLF = true;
51 #endif
52 }
53 else if( EQUAL(pszCRLFFormat, "CRLF") )
54 {
55 bUseCRLF = true;
56 }
57 else if( EQUAL(pszCRLFFormat, "LF") )
58 {
59 bUseCRLF = false;
60 }
61 else
62 {
63 CPLError( CE_Warning, CPLE_AppDefined,
64 "LINEFORMAT=%s not understood, use one of CRLF or LF.",
65 pszCRLFFormat );
66 #ifdef WIN32
67 bUseCRLF = true;
68 #endif
69 }
70
71 if( bUseCRLF )
72 pszEOL = "\r\n";
73 }
74
75 /************************************************************************/
detail(&mut self, val: i32) -> &mut Self76 /* ~OGRPGDumpDataSource() */
77 /************************************************************************/
78
79 OGRPGDumpDataSource::~OGRPGDumpDataSource()
80
81 {
82 EndCopy();
83 for( int i = 0; i < nLayers; i++ )
84 delete papoLayers[i];
85
86 if( fp )
87 {
88 LogCommit();
89 VSIFCloseL(fp);
90 fp = nullptr;
91 }
92 CPLFree(papoLayers);
93 CPLFree(pszName);
94 }
95
96 /************************************************************************/
97 /* LogStartTransaction() */
98 /************************************************************************/
99
100 void OGRPGDumpDataSource::LogStartTransaction()
101 {
102 if( bInTransaction )
103 return;
alt_key(&mut self, val: bool) -> &mut Self104 bInTransaction = true;
105 Log("BEGIN");
106 }
107
108 /************************************************************************/
109 /* LogCommit() */
110 /************************************************************************/
111
112 void OGRPGDumpDataSource::LogCommit()
113 {
114 EndCopy();
115
116 if( !bInTransaction )
117 return;
ctrl_key(&mut self, val: bool) -> &mut Self118 bInTransaction = false;
119 Log("COMMIT");
120 }
121
122 /************************************************************************/
123 /* OGRPGCommonLaunderName() */
124 /************************************************************************/
125
126 char *OGRPGCommonLaunderName( const char *pszSrcName,
127 const char* pszDebugPrefix )
128
129 {
130 char *pszSafeName = CPLStrdup( pszSrcName );
131
132 for( int i = 0; pszSafeName[i] != '\0'; i++ )
133 {
134 pszSafeName[i] = (char) tolower( pszSafeName[i] );
meta_key(&mut self, val: bool) -> &mut Self135 if( pszSafeName[i] == '\'' ||
136 pszSafeName[i] == '-' ||
137 pszSafeName[i] == '#' )
138 {
139 pszSafeName[i] = '_';
140 }
141 }
142
143 if( strcmp(pszSrcName,pszSafeName) != 0 )
144 CPLDebug(pszDebugPrefix, "LaunderName('%s') -> '%s'",
145 pszSrcName, pszSafeName);
146
147 return pszSafeName;
148 }
149
150 /************************************************************************/
151 /* ICreateLayer() */
modifier_alt_graph(&mut self, val: bool) -> &mut Self152 /************************************************************************/
153
154 OGRLayer *
155 OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
156 OGRSpatialReference *poSRS,
157 OGRwkbGeometryType eType,
158 char ** papszOptions )
159
160 {
161 const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
162 CPLString osFIDColumnName;
163 if (pszFIDColumnNameIn == nullptr)
164 osFIDColumnName = "ogc_fid";
165 else
166 {
167 if( CPLFetchBool(papszOptions,"LAUNDER", true) )
168 {
169 char *pszLaunderedFid =
170 OGRPGCommonLaunderName(pszFIDColumnNameIn, "PGDump");
171 osFIDColumnName = pszLaunderedFid;
172 CPLFree(pszLaunderedFid);
173 }
174 else
175 {
176 osFIDColumnName = pszFIDColumnNameIn;
177 }
178 }
179 const CPLString osFIDColumnNameEscaped =
180 OGRPGDumpEscapeColumnName(osFIDColumnName);
181
182 if (STARTS_WITH(pszLayerName, "pg"))
183 {
184 CPLError(CE_Warning, CPLE_AppDefined,
185 "The layer name should not begin by 'pg' as it is a reserved "
186 "prefix");
187 }
188
189 bool bHavePostGIS = true;
190 // bHavePostGIS = CPLFetchBool(papszOptions, "POSTGIS", true);
191
192 const bool bCreateTable = CPLFetchBool(papszOptions, "CREATE_TABLE", true);
193 const bool bCreateSchema =
194 CPLFetchBool(papszOptions, "CREATE_SCHEMA", true);
195 const char* pszDropTable =
196 CSLFetchNameValueDef(papszOptions, "DROP_TABLE", "IF_EXISTS");
197 int GeometryTypeFlags = 0;
198
199 if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
200 GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
201 if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
202 GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
203
204 int ForcedGeometryTypeFlags = -1;
205 const char* pszDim = CSLFetchNameValue( papszOptions, "DIM");
206 if( pszDim != nullptr )
207 {
208 if( EQUAL(pszDim, "XY") || EQUAL(pszDim, "2") )
209 {
210 GeometryTypeFlags = 0;
211 ForcedGeometryTypeFlags = GeometryTypeFlags;
212 }
213 else if( EQUAL(pszDim, "XYZ") || EQUAL(pszDim, "3") )
214 {
215 GeometryTypeFlags = OGRGeometry::OGR_G_3D;
216 ForcedGeometryTypeFlags = GeometryTypeFlags;
217 }
218 else if( EQUAL(pszDim, "XYM") )
219 {
220 GeometryTypeFlags = OGRGeometry::OGR_G_MEASURED;
221 ForcedGeometryTypeFlags = GeometryTypeFlags;
222 }
223 else if( EQUAL(pszDim, "XYZM") || EQUAL(pszDim, "4") )
224 {
225 GeometryTypeFlags = OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
226 ForcedGeometryTypeFlags = GeometryTypeFlags;
227 }
228 else
229 {
230 CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for DIM");
231 }
232 }
233
234 const int nDimension =
235 2 + ((GeometryTypeFlags & OGRGeometry::OGR_G_3D) ? 1 : 0)
236 + ((GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) ? 1 : 0);
237
238 /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
239 /* so they are still recorded in geometry_columns table ? (#4012) */
240 const bool bNoneAsUnknown =
241 CPLTestBool(
242 CSLFetchNameValueDef(papszOptions, "NONE_AS_UNKNOWN", "NO"));
243
244 if( bNoneAsUnknown && eType == wkbNone )
245 eType = wkbUnknown;
246 else if( eType == wkbNone )
247 bHavePostGIS = false;
248
249 const bool bExtractSchemaFromLayerName =
250 CPLTestBool(CSLFetchNameValueDef(
251 papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
252
253 // Postgres Schema handling:
254
255 // Extract schema name from input layer name or passed with -lco SCHEMA.
256 // Set layer name to "schema.table" or to "table" if schema ==
257 // current_schema() Usage without schema name is backwards compatible
258
259 const char* pszDotPos = strstr(pszLayerName,".");
260 char *pszTableName = nullptr;
261 char *pszSchemaName = nullptr;
262
263 if ( pszDotPos != nullptr && bExtractSchemaFromLayerName )
264 {
265 const int length = static_cast<int>(pszDotPos - pszLayerName);
266 pszSchemaName = (char*)CPLMalloc(length+1);
267 strncpy(pszSchemaName, pszLayerName, length);
268 pszSchemaName[length] = '\0';
269
270 if( CPLFetchBool(papszOptions, "LAUNDER", true) )
271 pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PGDump" ); //skip "."
272 else
273 pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
274 }
275 else
276 {
277 pszSchemaName = nullptr;
278 if( CPLFetchBool(papszOptions, "LAUNDER", true) )
279 pszTableName = OGRPGCommonLaunderName( pszLayerName, "PGDump" ); //skip "."
280 else
281 pszTableName = CPLStrdup( pszLayerName ); //skip "."
282 }
283
284 LogCommit();
285
286 /* -------------------------------------------------------------------- */
287 /* Set the default schema for the layers. */
288 /* -------------------------------------------------------------------- */
289 CPLString osCommand;
290
291 if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != nullptr )
292 {
293 CPLFree(pszSchemaName);
294 pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
295 if( bCreateSchema )
296 {
297 osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName);
298 Log(osCommand);
299 }
300 }
301
302 if ( pszSchemaName == nullptr)
303 {
304 pszSchemaName = CPLStrdup("public");
305 }
306
307 /* -------------------------------------------------------------------- */
308 /* Do we already have this layer? */
309 /* -------------------------------------------------------------------- */
310 for( int iLayer = 0; iLayer < nLayers; iLayer++ )
311 {
312 if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
313 {
314 CPLError( CE_Failure, CPLE_AppDefined,
315 "Layer %s already exists, CreateLayer failed.\n",
316 pszLayerName );
317 CPLFree( pszTableName );
318 CPLFree( pszSchemaName );
319 return nullptr;
320 }
321 }
322
323 if( bCreateTable && (EQUAL(pszDropTable, "YES") ||
324 EQUAL(pszDropTable, "ON") ||
325 EQUAL(pszDropTable, "TRUE") ||
326 EQUAL(pszDropTable, "IF_EXISTS")) )
327 {
328 if (EQUAL(pszDropTable, "IF_EXISTS"))
329 osCommand.Printf("DROP TABLE IF EXISTS \"%s\".\"%s\" CASCADE",
330 pszSchemaName, pszTableName );
331 else
332 osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE",
333 pszSchemaName, pszTableName );
334 Log(osCommand);
335 }
336
337 /* -------------------------------------------------------------------- */
338 /* Handle the GEOM_TYPE option. */
339 /* -------------------------------------------------------------------- */
340 const char *pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
341 if( pszGeomType == nullptr )
342 {
343 pszGeomType = "geometry";
344 }
345
346 if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography"))
347 {
348 CPLError(
349 CE_Failure, CPLE_AppDefined,
350 "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or "
351 "'geography'. Creation of layer %s with GEOM_TYPE %s has failed.",
352 pszLayerName, pszGeomType );
353 CPLFree( pszTableName );
354 CPLFree( pszSchemaName );
355 return nullptr;
356 }
357
358 /* -------------------------------------------------------------------- */
359 /* Try to get the SRS Id of this spatial reference system, */
360 /* adding tot the srs table if needed. */
361 /* -------------------------------------------------------------------- */
362 const char* pszPostgisVersion =
363 CSLFetchNameValueDef( papszOptions, "POSTGIS_VERSION", "2.2" );
364 const int nPostGISMajor = atoi(pszPostgisVersion);
365 const char* pszPostgisVersionDot = strchr(pszPostgisVersion, '.');
366 const int nPostGISMinor =
367 pszPostgisVersionDot ? atoi(pszPostgisVersionDot+1) : 0;
368 const int nUnknownSRSId = nPostGISMajor >= 2 ? 0 : -1;
369
370 int nSRSId = nUnknownSRSId;
371 int nForcedSRSId = -2;
372 if( CSLFetchNameValue( papszOptions, "SRID") != nullptr )
373 {
374 nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
375 nForcedSRSId = nSRSId;
376 }
377 else
378 {
379 if( poSRS )
380 {
381 const char* pszAuthorityName = poSRS->GetAuthorityName(nullptr);
382 if( pszAuthorityName != nullptr && EQUAL( pszAuthorityName, "EPSG" ) )
383 {
384 /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
385 nSRSId = atoi( poSRS->GetAuthorityCode(nullptr) );
386 }
387 else
388 {
389 const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
390 if( pszGeogCSName != nullptr &&
391 EQUAL(pszGeogCSName, "GCS_WGS_1984") )
392 {
393 nSRSId = 4326;
394 }
395 }
396 }
397 }
398
399 CPLString osEscapedTableNameSingleQuote =
400 OGRPGDumpEscapeString(pszTableName);
401 const char* pszEscapedTableNameSingleQuote =
402 osEscapedTableNameSingleQuote.c_str();
403
404 const char *pszGeometryType = OGRToOGCGeomType(eType);
405
406 const char *pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
407 if( bHavePostGIS && !EQUAL(pszGeomType, "geography") )
408 {
409 if( pszGFldName == nullptr )
410 pszGFldName = "wkb_geometry";
411
412 if( nPostGISMajor < 2 )
413 {
414 // Sometimes there is an old cruft entry in the geometry_columns
415 // table if things were not properly cleaned up before. We make
416 // an effort to clean out such cruft.
417 //
418 // Note: PostGIS 2.0 defines geometry_columns as a view (no clean up
419 // is needed).
420
421 osCommand.Printf(
422 "DELETE FROM geometry_columns "
423 "WHERE f_table_name = %s AND f_table_schema = '%s'",
424 pszEscapedTableNameSingleQuote, pszSchemaName );
425 if( bCreateTable )
426 Log(osCommand);
427 }
428 }
429
430 LogStartTransaction();
431
432 /* -------------------------------------------------------------------- */
433 /* Create a basic table with the FID. Also include the */
434 /* geometry if this is not a PostGIS enabled table. */
435 /* -------------------------------------------------------------------- */
436 const bool bFID64 = CPLFetchBool(papszOptions, "FID64", false);
437 const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL";
438
439 CPLString osCreateTable;
440 const bool bTemporary = CPLFetchBool( papszOptions, "TEMPORARY", false );
441 if( bTemporary )
442 {
443 CPLFree(pszSchemaName);
444 pszSchemaName = CPLStrdup("pg_temp_1");
445 osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName);
446 }
447 else
448 {
449 osCreateTable.Printf("CREATE%s TABLE \"%s\".\"%s\"",
450 CPLFetchBool( papszOptions, "UNLOGGED", false ) ?
451 " UNLOGGED": "",
452 pszSchemaName, pszTableName);
453 }
454
455 if( !bHavePostGIS )
456 {
457 if (eType == wkbNone)
458 osCommand.Printf(
459 "%s ( "
460 " %s %s, "
461 " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
462 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
463 pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
464 else
465 osCommand.Printf(
466 "%s ( "
467 " %s %s, "
468 " WKB_GEOMETRY %s, "
469 " CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
470 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
471 pszSerialType, pszGeomType, pszTableName,
472 osFIDColumnNameEscaped.c_str() );
473 }
474 else if ( EQUAL(pszGeomType, "geography") )
475 {
476 if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != nullptr )
477 pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
478 else
479 pszGFldName = "the_geog";
480
481 const char *suffix = "";
482 if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) &&
483 (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
484 {
485 suffix = "ZM";
486 }
487 else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
488 {
489 suffix = "M";
490 }
491 else if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
492 {
493 suffix = "Z";
494 }
495
496 if( nSRSId )
497 osCommand.Printf(
498 "%s ( %s %s, \"%s\" geography(%s%s,%d), "
499 "CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
500 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
501 pszSerialType, pszGFldName, pszGeometryType, suffix, nSRSId,
502 pszTableName, osFIDColumnNameEscaped.c_str() );
503 else
504 osCommand.Printf(
505 "%s ( %s %s, \"%s\" geography(%s%s), "
506 "CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
507 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
508 pszSerialType, pszGFldName, pszGeometryType, suffix,
509 pszTableName, osFIDColumnNameEscaped.c_str() );
510 }
511 else
512 {
513 osCommand.Printf(
514 "%s ( %s %s, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
515 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
516 pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
517 }
518
519 if( bCreateTable )
520 Log(osCommand);
521
522 /* -------------------------------------------------------------------- */
523 /* Eventually we should be adding this table to a table of */
524 /* "geometric layers", capturing the WKT projection, and */
525 /* perhaps some other housekeeping. */
526 /* -------------------------------------------------------------------- */
527 if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography") )
528 {
529 const char *suffix = "";
530 if( GeometryTypeFlags == static_cast<int>(OGRGeometry::OGR_G_MEASURED) &&
531 wkbFlatten(eType) != wkbUnknown )
532 {
533 suffix = "M";
534 }
535
536 osCommand.Printf(
537 "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s%s',%d)",
538 pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
539 nSRSId, pszGeometryType, suffix, nDimension );
540 Log(osCommand);
541 }
542
543 const char *pszSI = CSLFetchNameValueDef( papszOptions, "SPATIAL_INDEX", "GIST" );
544 const bool bCreateSpatialIndex = ( EQUAL(pszSI, "GIST") ||
545 EQUAL(pszSI, "SPGIST") || EQUAL(pszSI, "BRIN") ||
546 EQUAL(pszSI, "YES") || EQUAL(pszSI, "ON") || EQUAL(pszSI, "TRUE") );
547 if( !bCreateSpatialIndex && !EQUAL(pszSI, "NO") && !EQUAL(pszSI, "OFF") &&
548 !EQUAL(pszSI, "FALSE") && !EQUAL(pszSI, "NONE") )
549 {
550 CPLError(CE_Warning, CPLE_NotSupported,
551 "SPATIAL_INDEX=%s not supported", pszSI);
552 }
553 const char* pszSpatialIndexType = EQUAL(pszSI, "SPGIST") ? "SPGIST" :
554 EQUAL(pszSI, "BRIN") ? "BRIN" : "GIST";
555
556 if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
557 {
558 /* -------------------------------------------------------------------- */
559 /* Create the spatial index. */
560 /* */
561 /* We're doing this before we add geometry and record to the table */
562 /* so this may not be exactly the best way to do it. */
563 /* -------------------------------------------------------------------- */
564 osCommand.Printf(
565 "CREATE INDEX \"%s_%s_geom_idx\" "
566 "ON \"%s\".\"%s\" "
567 "USING %s (\"%s\")",
568 pszTableName, pszGFldName, pszSchemaName, pszTableName,
569 pszSpatialIndexType,
570 pszGFldName);
571
572 Log(osCommand);
573 }
574
575 /* -------------------------------------------------------------------- */
576 /* Create the layer object. */
577 /* -------------------------------------------------------------------- */
578 const bool bWriteAsHex =
579 !CPLFetchBool(papszOptions, "WRITE_EWKT_GEOM", false);
580
581 OGRPGDumpLayer *poLayer =
582 new OGRPGDumpLayer( this, pszSchemaName, pszTableName,
583 osFIDColumnName, bWriteAsHex, bCreateTable );
584 poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
585 poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
586
587 const char* pszOverrideColumnTypes =
588 CSLFetchNameValue( papszOptions, "COLUMN_TYPES" );
589 poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
590 poLayer->SetUnknownSRSId(nUnknownSRSId);
591 poLayer->SetForcedSRSId(nForcedSRSId);
592 poLayer->SetCreateSpatialIndex(bCreateSpatialIndex, pszSpatialIndexType);
593 poLayer->SetPostGISVersion(nPostGISMajor, nPostGISMinor);
594 poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
595
596 const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
597 if( pszDescription != nullptr )
598 poLayer->SetForcedDescription( pszDescription );
599
600 if( bHavePostGIS )
601 {
602 OGRGeomFieldDefn oTmp( pszGFldName, eType );
603 OGRPGDumpGeomFieldDefn *poGeomField =
604 new OGRPGDumpGeomFieldDefn(&oTmp);
605 poGeomField->nSRSId = nSRSId;
606 poGeomField->GeometryTypeFlags = GeometryTypeFlags;
607 poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
608 }
609 else if( pszGFldName )
610 poLayer->SetGeometryFieldName(pszGFldName);
611
612 /* -------------------------------------------------------------------- */
613 /* Add layer to data source layer list. */
614 /* -------------------------------------------------------------------- */
615 papoLayers = (OGRPGDumpLayer **)
616 CPLRealloc( papoLayers, sizeof(OGRPGDumpLayer *) * (nLayers+1) );
617
618 papoLayers[nLayers++] = poLayer;
619
620 CPLFree( pszTableName );
621 CPLFree( pszSchemaName );
622
623 return poLayer;
624 }
625
626 /************************************************************************/
627 /* TestCapability() */
628 /************************************************************************/
629
630 int OGRPGDumpDataSource::TestCapability( const char * pszCap )
631
632 {
633 if( EQUAL(pszCap,ODsCCreateLayer) )
634 return TRUE;
635 else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
636 return TRUE;
637 else if( EQUAL(pszCap,ODsCCurveGeometries) )
638 return TRUE;
639 else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
640 return TRUE;
641 else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
642 return TRUE;
643 else
644 return FALSE;
645 }
646
647 /************************************************************************/
648 /* GetLayer() */
649 /************************************************************************/
650
651 OGRLayer *OGRPGDumpDataSource::GetLayer( int iLayer )
652
653 {
654 if( iLayer < 0 || iLayer >= nLayers )
655 return nullptr;
656 else
657 return papoLayers[iLayer];
658 }
659
660 /************************************************************************/
661 /* Log() */
662 /************************************************************************/
663
664 bool OGRPGDumpDataSource::Log( const char* pszStr, bool bAddSemiColumn )
665 {
666 if( fp == nullptr )
667 {
668 if( bTriedOpen )
669 return false;
670 bTriedOpen = true;
671 fp = VSIFOpenL(pszName, "wb");
672 if (fp == nullptr)
673 {
674 CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", pszName);
675 return false;
676 }
677 }
678
679 if( bAddSemiColumn )
680 VSIFPrintfL(fp, "%s;%s", pszStr, pszEOL);
681 else
682 VSIFPrintfL(fp, "%s%s", pszStr, pszEOL);
683 return true;
684 }
685
686 /************************************************************************/
687 /* StartCopy() */
688 /************************************************************************/
689 void OGRPGDumpDataSource::StartCopy( OGRPGDumpLayer *poPGLayer )
690 {
691 EndCopy();
692 poLayerInCopyMode = poPGLayer;
693 }
694
695 /************************************************************************/
696 /* EndCopy() */
697 /************************************************************************/
698 OGRErr OGRPGDumpDataSource::EndCopy()
699 {
700 if( poLayerInCopyMode != nullptr )
701 {
702 OGRErr result = poLayerInCopyMode->EndCopy();
703 poLayerInCopyMode = nullptr;
704
705 return result;
706 }
707
708 return OGRERR_NONE;
709 }
710