1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: Simple client for translating between formats.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
9 * Copyright (c) 2008-2015, Even Rouault <even dot rouault at spatialys.com>
10 * Copyright (c) 2015, Faza Mahamood
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "cpl_port.h"
32 #include "gdal_utils.h"
33 #include "gdal_utils_priv.h"
34
35 #include <cassert>
36 #include <climits>
37 #include <cstdio>
38 #include <cstdlib>
39 #include <cstring>
40
41 #include <algorithm>
42 #include <map>
43 #include <memory>
44 #include <set>
45 #include <unordered_set>
46 #include <string>
47 #include <utility>
48 #include <vector>
49
50 #include "commonutils.h"
51 #include "cpl_conv.h"
52 #include "cpl_error.h"
53 #include "cpl_progress.h"
54 #include "cpl_string.h"
55 #include "cpl_vsi.h"
56 #include "gdal.h"
57 #include "gdal_alg.h"
58 #include "gdal_alg_priv.h"
59 #include "gdal_priv.h"
60 #include "ogr_api.h"
61 #include "ogr_core.h"
62 #include "ogr_feature.h"
63 #include "ogr_featurestyle.h"
64 #include "ogr_geometry.h"
65 #include "ogr_p.h"
66 #include "ogr_spatialref.h"
67 #include "ogrlayerdecorator.h"
68 #include "ogrsf_frmts.h"
69
70 CPL_CVSID("$Id: ogr2ogr_lib.cpp 28cd152257db832c88c249800e1a8f546404918c 2021-10-13 15:43:32 +0200 Even Rouault $")
71
72 typedef enum
73 {
74 GEOMOP_NONE,
75 GEOMOP_SEGMENTIZE,
76 GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY,
77 } GeomOperation;
78
79 typedef enum
80 {
81 GTC_DEFAULT,
82 GTC_PROMOTE_TO_MULTI,
83 GTC_CONVERT_TO_LINEAR,
84 GTC_CONVERT_TO_CURVE,
85 GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR,
86 } GeomTypeConversion;
87
88 #define GEOMTYPE_UNCHANGED -2
89
90 #define COORD_DIM_UNCHANGED -1
91 #define COORD_DIM_LAYER_DIM -2
92 #define COORD_DIM_XYM -3
93
94 /************************************************************************/
95 /* GDALVectorTranslateOptions */
96 /************************************************************************/
97
98 /** Options for use with GDALVectorTranslate(). GDALVectorTranslateOptions* must be allocated and
99 * freed with GDALVectorTranslateOptionsNew() and GDALVectorTranslateOptionsFree() respectively.
100 */
101 struct GDALVectorTranslateOptions
102 {
103 /*! continue after a failure, skipping the failed feature */
104 bool bSkipFailures;
105
106 /*! use layer level transaction. If set to FALSE, then it is interpreted as dataset level transaction. */
107 int nLayerTransaction;
108
109 /*! force the use of particular transaction type based on GDALVectorTranslate::nLayerTransaction */
110 bool bForceTransaction;
111
112 /*! group nGroupTransactions features per transaction (default 20000). Increase the value for better
113 performance when writing into DBMS drivers that have transaction support. nGroupTransactions can
114 be set to -1 to load the data into a single transaction */
115 int nGroupTransactions;
116
117 /*! If provided, only the feature with this feature id will be reported. Operates exclusive of
118 the spatial or attribute queries. Note: if you want to select several features based on their
119 feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL.
120 So GDALVectorTranslateOptions::pszWHERE = "fid in (1,3,5)" would select features 1, 3 and 5. */
121 GIntBig nFIDToFetch;
122
123 /*! allow or suppress progress monitor and other non-error output */
124 bool bQuiet;
125
126 /*! output file format name */
127 char *pszFormat;
128
129 /*! list of layers of the source dataset which needs to be selected */
130 char **papszLayers;
131
132 /*! dataset creation option (format specific) */
133 char **papszDSCO;
134
135 /*! layer creation option (format specific) */
136 char **papszLCO;
137
138 /*! access modes */
139 GDALVectorTranslateAccessMode eAccessMode;
140
141 /*! It has the effect of adding, to existing target layers, the new fields found in source layers.
142 This option is useful when merging files that have non-strictly identical structures. This might
143 not work for output formats that don't support adding fields to existing non-empty layers. */
144 bool bAddMissingFields;
145
146 /*! It must be set to true to trigger reprojection, otherwise only SRS assignment is done. */
147 bool bTransform;
148
149 /*! output SRS. GDALVectorTranslateOptions::bTransform must be set to true to trigger reprojection,
150 otherwise only SRS assignment is done. */
151 char *pszOutputSRSDef;
152
153 /*! override source SRS */
154 char *pszSourceSRSDef;
155
156 /*! PROJ pipeline */
157 char *pszCTPipeline;
158
159 bool bNullifyOutputSRS;
160
161 /*! If set to false, then field name matching between source and existing target layer is done
162 in a more relaxed way if the target driver has an implementation for it. */
163 bool bExactFieldNameMatch;
164
165 /*! an alternate name to the new layer */
166 char *pszNewLayerName;
167
168 /*! attribute query (like SQL WHERE) */
169 char *pszWHERE;
170
171 /*! name of the geometry field on which the spatial filter operates on. */
172 char *pszGeomField;
173
174 /*! list of fields from input layer to copy to the new layer. A field is skipped if
175 mentioned previously in the list even if the input layer has duplicate field names.
176 (Defaults to all; any field is skipped if a subsequent field with same name is
177 found.) Geometry fields can also be specified in the list. */
178 char **papszSelFields;
179
180 /*! SQL statement to execute. The resulting table/layer will be saved to the output. */
181 char *pszSQLStatement;
182
183 /*! SQL dialect. In some cases can be used to use (unoptimized) OGR SQL instead of the
184 native SQL of an RDBMS by using "OGRSQL". The "SQLITE" dialect can also be used with
185 any datasource. */
186 char *pszDialect;
187
188 /*! the geometry type for the created layer */
189 int eGType;
190
191 GeomTypeConversion eGeomTypeConversion;
192
193 /*! Geometric operation to perform */
194 GeomOperation eGeomOp;
195
196 /*! the parameter to geometric operation */
197 double dfGeomOpParam;
198
199 /*! Whether to run MakeValid */
200 bool bMakeValid;
201
202 /*! list of field types to convert to a field of type string in the destination layer.
203 Valid types are: Integer, Integer64, Real, String, Date, Time, DateTime, Binary,
204 IntegerList, Integer64List, RealList, StringList. Special value "All" can be
205 used to convert all fields to strings. This is an alternate way to using the CAST
206 operator of OGR SQL, that may avoid typing a long SQL query. Note that this does
207 not influence the field types used by the source driver, and is only an afterwards
208 conversion. */
209 char **papszFieldTypesToString;
210
211 /*! list of field types and the field type after conversion in the destination layer.
212 ("srctype1=dsttype1","srctype2=dsttype2",...).
213 Valid types are : Integer, Integer64, Real, String, Date, Time, DateTime, Binary,
214 IntegerList, Integer64List, RealList, StringList. Types can also include subtype
215 between parenthesis, such as Integer(Boolean), Real(Float32), ... Special value
216 "All" can be used to convert all fields to another type. This is an alternate way to
217 using the CAST operator of OGR SQL, that may avoid typing a long SQL query.
218 This is a generalization of GDALVectorTranslateOptions::papszFieldTypeToString. Note that this does not influence
219 the field types used by the source driver, and is only an afterwards conversion. */
220 char **papszMapFieldType;
221
222 /*! set field width and precision to 0 */
223 bool bUnsetFieldWidth;
224
225 /*! display progress on terminal. Only works if input layers have the "fast feature count"
226 capability */
227 bool bDisplayProgress;
228
229 /*! split geometries crossing the dateline meridian */
230 bool bWrapDateline;
231
232 /*! offset from dateline in degrees (default long. = +/- 10deg, geometries
233 within 170deg to -170deg will be split) */
234 double dfDateLineOffset;
235
236 /*! clip geometries when it is set to true */
237 bool bClipSrc;
238
239 OGRGeometryH hClipSrc;
240
241 /*! clip datasource */
242 char *pszClipSrcDS;
243
244 /*! select desired geometries using an SQL query */
245 char *pszClipSrcSQL;
246
247 /*! selected named layer from the source clip datasource */
248 char *pszClipSrcLayer;
249
250 /*! restrict desired geometries based on attribute query */
251 char *pszClipSrcWhere;
252
253 OGRGeometryH hClipDst;
254
255 /*! destination clip datasource */
256 char *pszClipDstDS;
257
258 /*! select desired geometries using an SQL query */
259 char *pszClipDstSQL;
260
261 /*! selected named layer from the destination clip datasource */
262 char *pszClipDstLayer;
263
264 /*! restrict desired geometries based on attribute query */
265 char *pszClipDstWhere;
266
267 /*! split fields of type StringList, RealList or IntegerList into as many fields
268 of type String, Real or Integer as necessary. */
269 bool bSplitListFields;
270
271 /*! limit the number of subfields created for each split field. */
272 int nMaxSplitListSubFields;
273
274 /*! produce one feature for each geometry in any kind of geometry collection in the
275 source file */
276 bool bExplodeCollections;
277
278 /*! uses the specified field to fill the Z coordinates of geometries */
279 char *pszZField;
280
281 /*! the list of field indexes to be copied from the source to the destination. The (n)th value
282 specified in the list is the index of the field in the target layer definition in which the
283 n(th) field of the source layer must be copied. Index count starts at zero. There must be
284 exactly as many values in the list as the count of the fields in the source layer.
285 We can use the "identity" option to specify that the fields should be transferred by using
286 the same order. This option should be used along with the
287 GDALVectorTranslateOptions::eAccessMode = ACCESS_APPEND option. */
288 char **papszFieldMap;
289
290 /*! force the coordinate dimension to nCoordDim (valid values are 2 or 3). This affects both
291 the layer geometry type, and feature geometries. */
292 int nCoordDim;
293
294 /*! destination dataset open option (format specific), only valid in update mode */
295 char **papszDestOpenOptions;
296
297 /*! If set to true, does not propagate not-nullable constraints to target layer if they exist
298 in source layer */
299 bool bForceNullable;
300
301 /*! If set to true, for each field with a coded field domains, create a field that contains
302 the description of the coded value. */
303 bool bResolveDomains;
304
305 /*! If set to true, empty string values will be treated as null */
306 bool bEmptyStrAsNull;
307
308 /*! If set to true, does not propagate default field values to target layer if they exist in
309 source layer */
310 bool bUnsetDefault;
311
312 /*! to prevent the new default behavior that consists in, if the output driver has a FID layer
313 creation option and we are not in append mode, to preserve the name of the source FID column
314 and source feature IDs */
315 bool bUnsetFid;
316
317 /*! use the FID of the source features instead of letting the output driver to automatically
318 assign a new one. If not in append mode, this behavior becomes the default if the output
319 driver has a FID layer creation option. In which case the name of the source FID column will
320 be used and source feature IDs will be attempted to be preserved. This behavior can be
321 disabled by option GDALVectorTranslateOptions::bUnsetFid */
322 bool bPreserveFID;
323
324 /*! set it to false to disable copying of metadata from source dataset and layers into target dataset and
325 layers, when supported by output driver. */
326 bool bCopyMD;
327
328 /*! list of metadata key and value to set on the output dataset, when supported by output driver.
329 ("META-TAG1=VALUE1","META-TAG2=VALUE2") */
330 char **papszMetadataOptions;
331
332 /*! override spatial filter SRS */
333 char *pszSpatSRSDef;
334
335 /*! size of the list GDALVectorTranslateOptions::pasGCPs */
336 int nGCPCount;
337
338 /*! list of ground control points to be added */
339 GDAL_GCP *pasGCPs;
340
341 /*! order of polynomial used for warping (1 to 3). The default is to select a polynomial
342 order based on the number of GCPs */
343 int nTransformOrder;
344
345 /*! spatial query extents, in the SRS of the source layer(s) (or the one specified with
346 GDALVectorTranslateOptions::pszSpatSRSDef). Only features whose geometry intersects the extents
347 will be selected. The geometries will not be clipped unless GDALVectorTranslateOptions::bClipSrc
348 is true. */
349 OGRGeometryH hSpatialFilter;
350
351 /*! the progress function to use */
352 GDALProgressFunc pfnProgress;
353
354 /*! pointer to the progress data variable */
355 void *pProgressData;
356
357 /*! Whether layer and feature native data must be transferred. */
358 bool bNativeData;
359
360 /*! Maximum number of features, or -1 if no limit. */
361 GIntBig nLimit;
362 };
363
364 struct TargetLayerInfo
365 {
366 OGRLayer * m_poSrcLayer = nullptr;
367 GIntBig m_nFeaturesRead = 0;
368 bool m_bPerFeatureCT = 0;
369 OGRLayer *m_poDstLayer = nullptr;
370 std::vector<std::unique_ptr<OGRCoordinateTransformation>> m_apoCT{};
371 std::vector<CPLStringList> m_aosTransformOptions{};
372 std::vector<int> m_anMap{};
373 struct ResolvedInfo
374 {
375 int nSrcField;
376 const OGRFieldDomain* poDomain;
377 };
378 std::map<int, ResolvedInfo> m_oMapResolved{};
379 std::map<const OGRFieldDomain*, std::map<std::string, std::string>> m_oMapDomainToKV{};
380 int m_iSrcZField = -1;
381 int m_iSrcFIDField = -1;
382 int m_iRequestedSrcGeomField = -1;
383 bool m_bPreserveFID = false;
384 const char *m_pszCTPipeline = nullptr;
385 };
386
387 struct AssociatedLayers
388 {
389 OGRLayer *poSrcLayer = nullptr;
390 std::unique_ptr<TargetLayerInfo> psInfo{};
391 };
392
393 class SetupTargetLayer
394 {
395 public:
396 GDALDataset *m_poSrcDS;
397 GDALDataset *m_poDstDS;
398 char **m_papszLCO;
399 OGRSpatialReference *m_poOutputSRS;
400 bool m_bNullifyOutputSRS;
401 char **m_papszSelFields;
402 bool m_bAppend;
403 bool m_bAddMissingFields;
404 int m_eGType;
405 GeomTypeConversion m_eGeomTypeConversion;
406 int m_nCoordDim;
407 bool m_bOverwrite;
408 char **m_papszFieldTypesToString;
409 char **m_papszMapFieldType;
410 bool m_bUnsetFieldWidth;
411 bool m_bExplodeCollections;
412 const char *m_pszZField;
413 char **m_papszFieldMap;
414 const char *m_pszWHERE;
415 bool m_bExactFieldNameMatch;
416 bool m_bQuiet;
417 bool m_bForceNullable;
418 bool m_bResolveDomains;
419 bool m_bUnsetDefault;
420 bool m_bUnsetFid;
421 bool m_bPreserveFID;
422 bool m_bCopyMD;
423 bool m_bNativeData;
424 bool m_bNewDataSource;
425 const char *m_pszCTPipeline;
426
427 std::unique_ptr<TargetLayerInfo> Setup(OGRLayer * poSrcLayer,
428 const char *pszNewLayerName,
429 GDALVectorTranslateOptions *psOptions,
430 GIntBig& nTotalEventsDone);
431 };
432
433 class LayerTranslator
434 {
435 public:
436 GDALDataset *m_poSrcDS;
437 GDALDataset *m_poODS;
438 bool m_bTransform;
439 bool m_bWrapDateline;
440 CPLString m_osDateLineOffset;
441 OGRSpatialReference *m_poOutputSRS;
442 bool m_bNullifyOutputSRS;
443 OGRSpatialReference *m_poUserSourceSRS;
444 OGRCoordinateTransformation *m_poGCPCoordTrans;
445 int m_eGType;
446 GeomTypeConversion m_eGeomTypeConversion;
447 bool m_bMakeValid;
448 int m_nCoordDim;
449 GeomOperation m_eGeomOp;
450 double m_dfGeomOpParam;
451 OGRGeometry *m_poClipSrc;
452 OGRGeometry *m_poClipDst;
453 bool m_bExplodeCollections;
454 bool m_bNativeData;
455 GIntBig m_nLimit;
456 OGRGeometryFactory::TransformWithOptionsCache m_transformWithOptionsCache;
457
458 int Translate(OGRFeature* poFeatureIn,
459 TargetLayerInfo* psInfo,
460 GIntBig nCountLayerFeatures,
461 GIntBig* pnReadFeatureCount,
462 GIntBig& nTotalEventsDone,
463 GDALProgressFunc pfnProgress,
464 void *pProgressArg,
465 GDALVectorTranslateOptions *psOptions);
466 };
467
468 static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
469 const char* pszNewLayerName,
470 bool bOverwrite,
471 bool* pbErrorOccurred,
472 bool* pbOverwriteActuallyDone,
473 bool* pbAddOverwriteLCO);
474
475 /************************************************************************/
476 /* LoadGeometry() */
477 /************************************************************************/
478
LoadGeometry(const char * pszDS,const char * pszSQL,const char * pszLyr,const char * pszWhere)479 static OGRGeometry* LoadGeometry( const char* pszDS,
480 const char* pszSQL,
481 const char* pszLyr,
482 const char* pszWhere)
483 {
484 GDALDataset *poDS =
485 reinterpret_cast<GDALDataset *>(OGROpen(pszDS, FALSE, nullptr));
486 if (poDS == nullptr)
487 return nullptr;
488
489 OGRLayer *poLyr = nullptr;
490 if (pszSQL != nullptr)
491 poLyr = poDS->ExecuteSQL( pszSQL, nullptr, nullptr );
492 else if (pszLyr != nullptr)
493 poLyr = poDS->GetLayerByName(pszLyr);
494 else
495 poLyr = poDS->GetLayer(0);
496
497 if (poLyr == nullptr)
498 {
499 CPLError(CE_Failure, CPLE_AppDefined,
500 "Failed to identify source layer from datasource." );
501 GDALClose(poDS);
502 return nullptr;
503 }
504
505 if (pszWhere)
506 poLyr->SetAttributeFilter(pszWhere);
507
508 OGRMultiPolygon *poMP = nullptr;
509 OGRFeature *poFeat = nullptr;
510 while ((poFeat = poLyr->GetNextFeature()) != nullptr)
511 {
512 OGRGeometry* poSrcGeom = poFeat->GetGeometryRef();
513 if (poSrcGeom)
514 {
515 const OGRwkbGeometryType eType =
516 wkbFlatten(poSrcGeom->getGeometryType());
517
518 if (poMP == nullptr)
519 poMP = new OGRMultiPolygon();
520
521 if( eType == wkbPolygon )
522 poMP->addGeometry( poSrcGeom );
523 else if( eType == wkbMultiPolygon )
524 {
525 OGRMultiPolygon* poSrcMP = poSrcGeom->toMultiPolygon();
526 const int nGeomCount = poSrcMP->getNumGeometries();
527
528 for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
529 {
530 poMP->addGeometry(
531 poSrcMP->getGeometryRef(iGeom) );
532 }
533 }
534 else
535 {
536 CPLError( CE_Failure, CPLE_AppDefined, "Geometry not of polygon type." );
537 OGRGeometryFactory::destroyGeometry(poMP);
538 OGRFeature::DestroyFeature(poFeat);
539 if( pszSQL != nullptr )
540 poDS->ReleaseResultSet( poLyr );
541 GDALClose(poDS);
542 return nullptr;
543 }
544 }
545
546 OGRFeature::DestroyFeature(poFeat);
547 }
548
549 if( pszSQL != nullptr )
550 poDS->ReleaseResultSet( poLyr );
551 GDALClose(poDS);
552
553 return poMP;
554 }
555
556 /************************************************************************/
557 /* OGRSplitListFieldLayer */
558 /************************************************************************/
559
560 typedef struct
561 {
562 int iSrcIndex;
563 OGRFieldType eType;
564 int nMaxOccurrences;
565 int nWidth;
566 } ListFieldDesc;
567
568 class OGRSplitListFieldLayer : public OGRLayer
569 {
570 OGRLayer *poSrcLayer;
571 OGRFeatureDefn *poFeatureDefn;
572 ListFieldDesc *pasListFields;
573 int nListFieldCount;
574 int nMaxSplitListSubFields;
575
576 OGRFeature *TranslateFeature(OGRFeature* poSrcFeature);
577
578 public:
579 OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
580 int nMaxSplitListSubFields);
581 virtual ~OGRSplitListFieldLayer();
582
583 bool BuildLayerDefn(GDALProgressFunc pfnProgress,
584 void *pProgressArg);
585
586 virtual OGRFeature *GetNextFeature() override;
587 virtual OGRFeature *GetFeature(GIntBig nFID) override;
588 virtual OGRFeatureDefn *GetLayerDefn() override;
589
ResetReading()590 virtual void ResetReading() override { poSrcLayer->ResetReading(); }
TestCapability(const char *)591 virtual int TestCapability(const char*) override { return FALSE; }
592
GetFeatureCount(int bForce=TRUE)593 virtual GIntBig GetFeatureCount( int bForce = TRUE ) override
594 {
595 return poSrcLayer->GetFeatureCount(bForce);
596 }
597
GetSpatialRef()598 virtual OGRSpatialReference *GetSpatialRef() override
599 {
600 return poSrcLayer->GetSpatialRef();
601 }
602
GetSpatialFilter()603 virtual OGRGeometry *GetSpatialFilter() override
604 {
605 return poSrcLayer->GetSpatialFilter();
606 }
607
GetStyleTable()608 virtual OGRStyleTable *GetStyleTable() override
609 {
610 return poSrcLayer->GetStyleTable();
611 }
612
SetSpatialFilter(OGRGeometry * poGeom)613 virtual void SetSpatialFilter( OGRGeometry *poGeom ) override
614 {
615 poSrcLayer->SetSpatialFilter(poGeom);
616 }
617
SetSpatialFilter(int iGeom,OGRGeometry * poGeom)618 virtual void SetSpatialFilter( int iGeom, OGRGeometry *poGeom ) override
619 {
620 poSrcLayer->SetSpatialFilter(iGeom, poGeom);
621 }
622
SetSpatialFilterRect(double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)623 virtual void SetSpatialFilterRect( double dfMinX, double dfMinY,
624 double dfMaxX, double dfMaxY ) override
625 {
626 poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
627 }
628
SetSpatialFilterRect(int iGeom,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)629 virtual void SetSpatialFilterRect( int iGeom,
630 double dfMinX, double dfMinY,
631 double dfMaxX, double dfMaxY ) override
632 {
633 poSrcLayer->SetSpatialFilterRect(iGeom, dfMinX, dfMinY, dfMaxX, dfMaxY);
634 }
635
SetAttributeFilter(const char * pszFilter)636 virtual OGRErr SetAttributeFilter( const char *pszFilter ) override
637 {
638 return poSrcLayer->SetAttributeFilter(pszFilter);
639 }
640 };
641
642 /************************************************************************/
643 /* OGRSplitListFieldLayer() */
644 /************************************************************************/
645
OGRSplitListFieldLayer(OGRLayer * poSrcLayerIn,int nMaxSplitListSubFieldsIn)646 OGRSplitListFieldLayer::OGRSplitListFieldLayer(OGRLayer* poSrcLayerIn,
647 int nMaxSplitListSubFieldsIn) :
648 poSrcLayer(poSrcLayerIn),
649 poFeatureDefn(nullptr),
650 pasListFields(nullptr),
651 nListFieldCount(0),
652 nMaxSplitListSubFields(
653 nMaxSplitListSubFieldsIn < 0 ? INT_MAX : nMaxSplitListSubFieldsIn)
654 {}
655
656 /************************************************************************/
657 /* ~OGRSplitListFieldLayer() */
658 /************************************************************************/
659
~OGRSplitListFieldLayer()660 OGRSplitListFieldLayer::~OGRSplitListFieldLayer()
661 {
662 if( poFeatureDefn )
663 poFeatureDefn->Release();
664
665 CPLFree(pasListFields);
666 }
667
668 /************************************************************************/
669 /* BuildLayerDefn() */
670 /************************************************************************/
671
BuildLayerDefn(GDALProgressFunc pfnProgress,void * pProgressArg)672 bool OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
673 void *pProgressArg)
674 {
675 CPLAssert(poFeatureDefn == nullptr);
676
677 OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
678
679 int nSrcFields = poSrcFieldDefn->GetFieldCount();
680 pasListFields = static_cast<ListFieldDesc *>(
681 CPLCalloc(sizeof(ListFieldDesc), nSrcFields));
682 nListFieldCount = 0;
683
684 /* Establish the list of fields of list type */
685 for( int i=0; i<nSrcFields; ++i )
686 {
687 OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
688 if (eType == OFTIntegerList ||
689 eType == OFTInteger64List ||
690 eType == OFTRealList ||
691 eType == OFTStringList)
692 {
693 pasListFields[nListFieldCount].iSrcIndex = i;
694 pasListFields[nListFieldCount].eType = eType;
695 if (nMaxSplitListSubFields == 1)
696 pasListFields[nListFieldCount].nMaxOccurrences = 1;
697 nListFieldCount++;
698 }
699 }
700
701 if (nListFieldCount == 0)
702 return false;
703
704 /* No need for full scan if the limit is 1. We just to have to create */
705 /* one and a single one field */
706 if (nMaxSplitListSubFields != 1)
707 {
708 poSrcLayer->ResetReading();
709
710 const GIntBig nFeatureCount =
711 poSrcLayer->TestCapability(OLCFastFeatureCount)
712 ? poSrcLayer->GetFeatureCount()
713 : 0;
714 GIntBig nFeatureIndex = 0;
715
716 /* Scan the whole layer to compute the maximum number of */
717 /* items for each field of list type */
718 OGRFeature* poSrcFeature = nullptr;
719 while( (poSrcFeature = poSrcLayer->GetNextFeature()) != nullptr )
720 {
721 for( int i=0; i<nListFieldCount; ++i )
722 {
723 int nCount = 0;
724 OGRField* psField =
725 poSrcFeature->GetRawFieldRef(pasListFields[i].iSrcIndex);
726 switch(pasListFields[i].eType)
727 {
728 case OFTIntegerList:
729 nCount = psField->IntegerList.nCount;
730 break;
731 case OFTRealList:
732 nCount = psField->RealList.nCount;
733 break;
734 case OFTStringList:
735 {
736 nCount = psField->StringList.nCount;
737 char** paList = psField->StringList.paList;
738 for(int j=0;j<nCount;j++)
739 {
740 int nWidth = static_cast<int>(strlen(paList[j]));
741 if (nWidth > pasListFields[i].nWidth)
742 pasListFields[i].nWidth = nWidth;
743 }
744 break;
745 }
746 default:
747 // cppcheck-suppress knownConditionTrueFalse
748 CPLAssert(false);
749 break;
750 }
751 if (nCount > pasListFields[i].nMaxOccurrences)
752 {
753 if (nCount > nMaxSplitListSubFields)
754 nCount = nMaxSplitListSubFields;
755 pasListFields[i].nMaxOccurrences = nCount;
756 }
757 }
758 OGRFeature::DestroyFeature(poSrcFeature);
759
760 nFeatureIndex ++;
761 if (pfnProgress != nullptr && nFeatureCount != 0)
762 pfnProgress(nFeatureIndex * 1.0 / nFeatureCount, "", pProgressArg);
763 }
764 }
765
766 /* Now let's build the target feature definition */
767
768 poFeatureDefn =
769 OGRFeatureDefn::CreateFeatureDefn( poSrcFieldDefn->GetName() );
770 poFeatureDefn->Reference();
771 poFeatureDefn->SetGeomType( wkbNone );
772
773 for( int i=0; i < poSrcFieldDefn->GetGeomFieldCount(); ++i )
774 {
775 poFeatureDefn->AddGeomFieldDefn(poSrcFieldDefn->GetGeomFieldDefn(i));
776 }
777
778 int iListField = 0;
779 for( int i=0;i<nSrcFields; ++i)
780 {
781 const OGRFieldType eType = poSrcFieldDefn->GetFieldDefn(i)->GetType();
782 if (eType == OFTIntegerList ||
783 eType == OFTInteger64List ||
784 eType == OFTRealList ||
785 eType == OFTStringList)
786 {
787 const int nMaxOccurrences =
788 pasListFields[iListField].nMaxOccurrences;
789 const int nWidth = pasListFields[iListField].nWidth;
790 iListField ++;
791 if (nMaxOccurrences == 1)
792 {
793 OGRFieldDefn oFieldDefn(poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(),
794 (eType == OFTIntegerList) ? OFTInteger :
795 (eType == OFTInteger64List) ? OFTInteger64 :
796 (eType == OFTRealList) ? OFTReal :
797 OFTString);
798 poFeatureDefn->AddFieldDefn(&oFieldDefn);
799 }
800 else
801 {
802 for(int j=0;j<nMaxOccurrences;j++)
803 {
804 CPLString osFieldName;
805 osFieldName.Printf("%s%d",
806 poSrcFieldDefn->GetFieldDefn(i)->GetNameRef(), j+1);
807 OGRFieldDefn oFieldDefn(osFieldName.c_str(),
808 (eType == OFTIntegerList) ? OFTInteger :
809 (eType == OFTInteger64List) ? OFTInteger64 :
810 (eType == OFTRealList) ? OFTReal :
811 OFTString);
812 oFieldDefn.SetWidth(nWidth);
813 poFeatureDefn->AddFieldDefn(&oFieldDefn);
814 }
815 }
816 }
817 else
818 {
819 poFeatureDefn->AddFieldDefn(poSrcFieldDefn->GetFieldDefn(i));
820 }
821 }
822
823 return true;
824 }
825
826 /************************************************************************/
827 /* TranslateFeature() */
828 /************************************************************************/
829
TranslateFeature(OGRFeature * poSrcFeature)830 OGRFeature *OGRSplitListFieldLayer::TranslateFeature(OGRFeature* poSrcFeature)
831 {
832 if (poSrcFeature == nullptr)
833 return nullptr;
834 if (poFeatureDefn == nullptr)
835 return poSrcFeature;
836
837 OGRFeature* poFeature = OGRFeature::CreateFeature(poFeatureDefn);
838 poFeature->SetFID(poSrcFeature->GetFID());
839 for(int i=0;i<poFeature->GetGeomFieldCount();i++)
840 {
841 poFeature->SetGeomFieldDirectly(i, poSrcFeature->StealGeometry(i));
842 }
843 poFeature->SetStyleString(poFeature->GetStyleString());
844
845 OGRFeatureDefn* poSrcFieldDefn = poSrcLayer->GetLayerDefn();
846 int nSrcFields = poSrcFeature->GetFieldCount();
847 int iDstField = 0;
848 int iListField = 0;
849
850 for( int iSrcField=0; iSrcField < nSrcFields; ++iSrcField)
851 {
852 const OGRFieldType eType =
853 poSrcFieldDefn->GetFieldDefn(iSrcField)->GetType();
854 OGRField* psField = poSrcFeature->GetRawFieldRef(iSrcField);
855 switch(eType)
856 {
857 case OFTIntegerList:
858 {
859 const int nCount = std::min(nMaxSplitListSubFields,
860 psField->IntegerList.nCount);
861 int* paList = psField->IntegerList.paList;
862 for( int j=0;j<nCount; ++j)
863 poFeature->SetField(iDstField + j, paList[j]);
864 iDstField += pasListFields[iListField].nMaxOccurrences;
865 iListField++;
866 break;
867 }
868 case OFTInteger64List:
869 {
870 const int nCount = std::min(nMaxSplitListSubFields,
871 psField->Integer64List.nCount);
872 GIntBig* paList = psField->Integer64List.paList;
873 for( int j=0; j < nCount; ++j )
874 poFeature->SetField(iDstField + j, paList[j]);
875 iDstField += pasListFields[iListField].nMaxOccurrences;
876 iListField++;
877 break;
878 }
879 case OFTRealList:
880 {
881 const int nCount = std::min(nMaxSplitListSubFields,
882 psField->RealList.nCount);
883 double* paList = psField->RealList.paList;
884 for( int j=0; j < nCount; ++j )
885 poFeature->SetField(iDstField + j, paList[j]);
886 iDstField += pasListFields[iListField].nMaxOccurrences;
887 iListField++;
888 break;
889 }
890 case OFTStringList:
891 {
892 const int nCount = std::min(nMaxSplitListSubFields,
893 psField->StringList.nCount);
894 char** paList = psField->StringList.paList;
895 for( int j=0; j < nCount; ++j )
896 poFeature->SetField(iDstField + j, paList[j]);
897 iDstField += pasListFields[iListField].nMaxOccurrences;
898 iListField++;
899 break;
900 }
901 default:
902 {
903 poFeature->SetField(iDstField, psField);
904 iDstField ++;
905 break;
906 }
907 }
908 }
909
910 OGRFeature::DestroyFeature(poSrcFeature);
911
912 return poFeature;
913 }
914
915 /************************************************************************/
916 /* GetNextFeature() */
917 /************************************************************************/
918
GetNextFeature()919 OGRFeature *OGRSplitListFieldLayer::GetNextFeature()
920 {
921 return TranslateFeature(poSrcLayer->GetNextFeature());
922 }
923
924 /************************************************************************/
925 /* GetFeature() */
926 /************************************************************************/
927
GetFeature(GIntBig nFID)928 OGRFeature *OGRSplitListFieldLayer::GetFeature(GIntBig nFID)
929 {
930 return TranslateFeature(poSrcLayer->GetFeature(nFID));
931 }
932
933 /************************************************************************/
934 /* GetLayerDefn() */
935 /************************************************************************/
936
GetLayerDefn()937 OGRFeatureDefn* OGRSplitListFieldLayer::GetLayerDefn()
938 {
939 if (poFeatureDefn == nullptr)
940 return poSrcLayer->GetLayerDefn();
941 return poFeatureDefn;
942 }
943
944 /************************************************************************/
945 /* GCPCoordTransformation() */
946 /* */
947 /* Apply GCP Transform to points */
948 /************************************************************************/
949
950 class GCPCoordTransformation : public OGRCoordinateTransformation
951 {
GCPCoordTransformation(const GCPCoordTransformation & other)952 GCPCoordTransformation(const GCPCoordTransformation& other):
953 hTransformArg(GDALCloneTransformer(other.hTransformArg)),
954 bUseTPS(other.bUseTPS),
955 poSRS(other.poSRS)
956 {
957 if( poSRS)
958 poSRS->Reference();
959 }
960
961 GCPCoordTransformation& operator= (const GCPCoordTransformation&) = delete;
962
963 public:
964
965 void *hTransformArg;
966 bool bUseTPS;
967 OGRSpatialReference* poSRS;
968
GCPCoordTransformation(int nGCPCount,const GDAL_GCP * pasGCPList,int nReqOrder,OGRSpatialReference * poSRSIn)969 GCPCoordTransformation( int nGCPCount,
970 const GDAL_GCP *pasGCPList,
971 int nReqOrder,
972 OGRSpatialReference* poSRSIn) :
973 hTransformArg(nullptr),
974 bUseTPS(nReqOrder < 0),
975 poSRS(poSRSIn)
976 {
977 if( nReqOrder < 0 )
978 {
979 hTransformArg =
980 GDALCreateTPSTransformer( nGCPCount, pasGCPList, FALSE );
981 }
982 else
983 {
984 hTransformArg =
985 GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, FALSE );
986 }
987 if( poSRS)
988 poSRS->Reference();
989 }
990
Clone() const991 OGRCoordinateTransformation* Clone() const override {
992 return new GCPCoordTransformation(*this);
993 }
994
IsValid() const995 bool IsValid() const { return hTransformArg != nullptr; }
996
~GCPCoordTransformation()997 virtual ~GCPCoordTransformation()
998 {
999 if( hTransformArg != nullptr )
1000 {
1001 GDALDestroyTransformer(hTransformArg);
1002 }
1003 if( poSRS)
1004 poSRS->Dereference();
1005 }
1006
GetSourceCS()1007 virtual OGRSpatialReference *GetSourceCS() override { return poSRS; }
GetTargetCS()1008 virtual OGRSpatialReference *GetTargetCS() override { return poSRS; }
1009
Transform(int nCount,double * x,double * y,double * z,double *,int * pabSuccess)1010 virtual int Transform( int nCount,
1011 double *x, double *y, double *z,
1012 double * /* t */,
1013 int *pabSuccess ) override
1014 {
1015 if( bUseTPS )
1016 return GDALTPSTransform( hTransformArg, FALSE,
1017 nCount, x, y, z, pabSuccess );
1018 else
1019 return GDALGCPTransform( hTransformArg, FALSE,
1020 nCount, x, y, z, pabSuccess );
1021 }
1022
GetInverse() const1023 virtual OGRCoordinateTransformation* GetInverse() const override { return nullptr; }
1024 };
1025
1026 /************************************************************************/
1027 /* CompositeCT */
1028 /************************************************************************/
1029
1030 class CompositeCT : public OGRCoordinateTransformation
1031 {
CompositeCT(const CompositeCT & other)1032 CompositeCT(const CompositeCT& other):
1033 poCT1(other.poCT1 ? other.poCT1->Clone(): nullptr),
1034 bOwnCT1(true),
1035 poCT2(other.poCT2 ? other.poCT2->Clone(): nullptr),
1036 bOwnCT2(true) {}
1037
1038 CompositeCT& operator= (const CompositeCT&) = delete;
1039
1040 public:
1041
1042 OGRCoordinateTransformation* poCT1;
1043 bool bOwnCT1;
1044 OGRCoordinateTransformation* poCT2;
1045 bool bOwnCT2;
1046
CompositeCT(OGRCoordinateTransformation * poCT1In,bool bOwnCT1In,OGRCoordinateTransformation * poCT2In,bool bOwnCT2In)1047 CompositeCT( OGRCoordinateTransformation* poCT1In, bool bOwnCT1In,
1048 OGRCoordinateTransformation* poCT2In, bool bOwnCT2In ) :
1049 poCT1(poCT1In),
1050 bOwnCT1(bOwnCT1In),
1051 poCT2(poCT2In),
1052 bOwnCT2(bOwnCT2In)
1053 {}
1054
~CompositeCT()1055 virtual ~CompositeCT()
1056 {
1057 if( bOwnCT1 )
1058 delete poCT1;
1059 if( bOwnCT2 )
1060 delete poCT2;
1061 }
1062
Clone() const1063 OGRCoordinateTransformation* Clone() const override {
1064 return new CompositeCT(*this);
1065 }
1066
GetSourceCS()1067 virtual OGRSpatialReference *GetSourceCS() override
1068 {
1069 return poCT1 ? poCT1->GetSourceCS() :
1070 poCT2 ? poCT2->GetSourceCS() : nullptr;
1071 }
1072
GetTargetCS()1073 virtual OGRSpatialReference *GetTargetCS() override
1074 {
1075 return poCT2 ? poCT2->GetTargetCS() :
1076 poCT1 ? poCT1->GetTargetCS() : nullptr;
1077 }
1078
Transform(int nCount,double * x,double * y,double * z,double * t,int * pabSuccess)1079 virtual int Transform( int nCount,
1080 double *x, double *y, double *z,
1081 double *t,
1082 int *pabSuccess ) override
1083 {
1084 int nResult = TRUE;
1085 if( poCT1 )
1086 nResult = poCT1->Transform(nCount, x, y, z, t, pabSuccess);
1087 if( nResult && poCT2 )
1088 nResult = poCT2->Transform(nCount, x, y, z, t, pabSuccess);
1089 return nResult;
1090 }
1091
GetInverse() const1092 virtual OGRCoordinateTransformation* GetInverse() const override { return nullptr; }
1093 };
1094
1095 /************************************************************************/
1096 /* AxisMappingCoordinateTransformation */
1097 /************************************************************************/
1098
1099 class AxisMappingCoordinateTransformation : public OGRCoordinateTransformation
1100 {
1101 public:
1102
1103 bool bSwapXY = false;
1104
AxisMappingCoordinateTransformation(const std::vector<int> & mappingIn,const std::vector<int> & mappingOut)1105 AxisMappingCoordinateTransformation( const std::vector<int>& mappingIn,
1106 const std::vector<int>& mappingOut )
1107 {
1108 if( mappingIn.size() >= 2 && mappingIn[0] == 1 && mappingIn[1] == 2 &&
1109 mappingOut.size() >= 2 && mappingOut[0] == 2 && mappingOut[1] == 1 )
1110 {
1111 bSwapXY = true;
1112 }
1113 else if( mappingIn.size() >= 2 && mappingIn[0] == 2 && mappingIn[1] == 1 &&
1114 mappingOut.size() >= 2 && mappingOut[0] == 1 && mappingOut[1] == 2 )
1115 {
1116 bSwapXY = true;
1117 }
1118 else
1119 {
1120 CPLError(CE_Failure, CPLE_NotSupported,
1121 "Unsupported axis transformation");
1122 }
1123 }
1124
~AxisMappingCoordinateTransformation()1125 ~AxisMappingCoordinateTransformation() override
1126 {
1127 }
1128
Clone() const1129 virtual OGRCoordinateTransformation *Clone() const override
1130 {
1131 return new AxisMappingCoordinateTransformation(*this);
1132 }
1133
GetSourceCS()1134 virtual OGRSpatialReference *GetSourceCS() override
1135 {
1136 return nullptr;
1137 }
1138
GetTargetCS()1139 virtual OGRSpatialReference *GetTargetCS() override
1140 {
1141 return nullptr;
1142 }
1143
Transform(int nCount,double * x,double * y,double *,double *,int * pabSuccess)1144 virtual int Transform( int nCount,
1145 double *x, double *y,
1146 double * /*z*/,
1147 double * /*t*/,
1148 int *pabSuccess ) override
1149 {
1150 for(int i = 0; i < nCount; i++ )
1151 {
1152 if( pabSuccess )
1153 pabSuccess[i] = true;
1154 if( bSwapXY )
1155 std::swap(x[i], y[i]);
1156 }
1157 return true;
1158 }
1159
GetInverse() const1160 virtual OGRCoordinateTransformation* GetInverse() const override { return nullptr; }
1161 };
1162
1163 /************************************************************************/
1164 /* ApplySpatialFilter() */
1165 /************************************************************************/
1166
1167 static
ApplySpatialFilter(OGRLayer * poLayer,OGRGeometry * poSpatialFilter,OGRSpatialReference * poSpatSRS,const char * pszGeomField,OGRSpatialReference * poSourceSRS)1168 void ApplySpatialFilter(OGRLayer* poLayer, OGRGeometry* poSpatialFilter,
1169 OGRSpatialReference* poSpatSRS,
1170 const char* pszGeomField,
1171 OGRSpatialReference* poSourceSRS)
1172 {
1173 if( poSpatialFilter == nullptr )
1174 return;
1175
1176 OGRGeometry* poSpatialFilterReprojected = nullptr;
1177 if( poSpatSRS )
1178 {
1179 poSpatialFilterReprojected = poSpatialFilter->clone();
1180 poSpatialFilterReprojected->assignSpatialReference(poSpatSRS);
1181 OGRSpatialReference* poSpatialFilterTargetSRS = poSourceSRS ? poSourceSRS : poLayer->GetSpatialRef();
1182 if( poSpatialFilterTargetSRS )
1183 poSpatialFilterReprojected->transformTo(poSpatialFilterTargetSRS);
1184 else
1185 CPLError(CE_Warning, CPLE_AppDefined, "cannot determine layer SRS for %s.", poLayer->GetDescription());
1186 }
1187
1188 if( pszGeomField != nullptr )
1189 {
1190 const int iGeomField =
1191 poLayer->GetLayerDefn()->GetGeomFieldIndex(pszGeomField);
1192 if( iGeomField >= 0 )
1193 poLayer->SetSpatialFilter( iGeomField,
1194 poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
1195 else
1196 CPLError(CE_Warning, CPLE_AppDefined,
1197 "Cannot find geometry field %s.",
1198 pszGeomField);
1199 }
1200 else
1201 {
1202 poLayer->SetSpatialFilter( poSpatialFilterReprojected ? poSpatialFilterReprojected : poSpatialFilter );
1203 }
1204
1205 delete poSpatialFilterReprojected;
1206 }
1207
1208 /************************************************************************/
1209 /* GetFieldType() */
1210 /************************************************************************/
1211
GetFieldType(const char * pszArg,int * pnSubFieldType)1212 static int GetFieldType(const char* pszArg, int* pnSubFieldType)
1213 {
1214 *pnSubFieldType = OFSTNone;
1215 const char* pszOpenParenthesis = strchr(pszArg, '(');
1216 const int nLengthBeforeParenthesis =
1217 pszOpenParenthesis
1218 ? static_cast<int>(pszOpenParenthesis - pszArg)
1219 : static_cast<int>(strlen(pszArg));
1220 for( int iType = 0; iType <= static_cast<int>(OFTMaxType); iType++ )
1221 {
1222 const char* pszFieldTypeName = OGRFieldDefn::GetFieldTypeName(
1223 static_cast<OGRFieldType>(iType));
1224 if( EQUALN(pszArg,pszFieldTypeName,nLengthBeforeParenthesis) &&
1225 pszFieldTypeName[nLengthBeforeParenthesis] == '\0' )
1226 {
1227 if( pszOpenParenthesis != nullptr )
1228 {
1229 *pnSubFieldType = -1;
1230 CPLString osArgSubType = pszOpenParenthesis + 1;
1231 if( !osArgSubType.empty() && osArgSubType.back() == ')' )
1232 osArgSubType.resize(osArgSubType.size()-1);
1233 for( int iSubType = 0;
1234 iSubType <= static_cast<int>(OFSTMaxSubType); iSubType++ )
1235 {
1236 const char* pszFieldSubTypeName = OGRFieldDefn::GetFieldSubTypeName(
1237 static_cast<OGRFieldSubType>(iSubType));
1238 if( EQUAL( pszFieldSubTypeName, osArgSubType ) )
1239 {
1240 *pnSubFieldType = iSubType;
1241 break;
1242 }
1243 }
1244 }
1245 return iType;
1246 }
1247 }
1248 return -1;
1249 }
1250
1251 /************************************************************************/
1252 /* IsNumber() */
1253 /************************************************************************/
1254
IsNumber(const char * pszStr)1255 static bool IsNumber(const char* pszStr)
1256 {
1257 if (*pszStr == '-' || *pszStr == '+')
1258 pszStr ++;
1259 if (*pszStr == '.')
1260 pszStr ++;
1261 return (*pszStr >= '0' && *pszStr <= '9');
1262 }
1263
1264 /************************************************************************/
1265 /* IsFieldType() */
1266 /************************************************************************/
1267
IsFieldType(const char * pszArg)1268 static bool IsFieldType(const char* pszArg)
1269 {
1270 int iSubType;
1271 return GetFieldType(pszArg, &iSubType) >= 0 && iSubType >= 0;
1272 }
1273
1274 /************************************************************************/
1275 /* GDALVectorTranslateOptionsClone() */
1276 /************************************************************************/
1277
1278 static
GDALVectorTranslateOptionsClone(const GDALVectorTranslateOptions * psOptionsIn)1279 GDALVectorTranslateOptions* GDALVectorTranslateOptionsClone(const GDALVectorTranslateOptions *psOptionsIn)
1280 {
1281 GDALVectorTranslateOptions* psOptions =
1282 static_cast<GDALVectorTranslateOptions *>(
1283 CPLMalloc(sizeof(GDALVectorTranslateOptions)));
1284 memcpy(psOptions, psOptionsIn, sizeof(GDALVectorTranslateOptions));
1285
1286 if( psOptionsIn->pszFormat) psOptions->pszFormat = CPLStrdup(psOptionsIn->pszFormat);
1287 if( psOptionsIn->pszOutputSRSDef ) psOptions->pszOutputSRSDef = CPLStrdup(psOptionsIn->pszOutputSRSDef);
1288 if( psOptionsIn->pszCTPipeline ) psOptions->pszCTPipeline = CPLStrdup(psOptionsIn->pszCTPipeline);
1289 if( psOptionsIn->pszSourceSRSDef ) psOptions->pszSourceSRSDef = CPLStrdup(psOptionsIn->pszSourceSRSDef);
1290 if( psOptionsIn->pszNewLayerName ) psOptions->pszNewLayerName = CPLStrdup(psOptionsIn->pszNewLayerName);
1291 if( psOptionsIn->pszWHERE ) psOptions->pszWHERE = CPLStrdup(psOptionsIn->pszWHERE);
1292 if( psOptionsIn->pszGeomField ) psOptions->pszGeomField = CPLStrdup(psOptionsIn->pszGeomField);
1293 if( psOptionsIn->pszSQLStatement ) psOptions->pszSQLStatement = CPLStrdup(psOptionsIn->pszSQLStatement);
1294 if( psOptionsIn->pszDialect ) psOptions->pszDialect = CPLStrdup(psOptionsIn->pszDialect);
1295 if( psOptionsIn->pszClipSrcDS ) psOptions->pszClipSrcDS = CPLStrdup(psOptionsIn->pszClipSrcDS);
1296 if( psOptionsIn->pszClipSrcSQL ) psOptions->pszClipSrcSQL = CPLStrdup(psOptionsIn->pszClipSrcSQL);
1297 if( psOptionsIn->pszClipSrcLayer ) psOptions->pszClipSrcLayer = CPLStrdup(psOptionsIn->pszClipSrcLayer);
1298 if( psOptionsIn->pszClipSrcWhere ) psOptions->pszClipSrcWhere = CPLStrdup(psOptionsIn->pszClipSrcWhere);
1299 if( psOptionsIn->pszClipDstDS ) psOptions->pszClipDstDS = CPLStrdup(psOptionsIn->pszClipDstDS);
1300 if( psOptionsIn->pszClipDstSQL ) psOptions->pszClipDstSQL = CPLStrdup(psOptionsIn->pszClipDstSQL);
1301 if( psOptionsIn->pszClipDstLayer ) psOptions->pszClipDstLayer = CPLStrdup(psOptionsIn->pszClipDstLayer);
1302 if( psOptionsIn->pszClipDstWhere ) psOptions->pszClipDstWhere = CPLStrdup(psOptionsIn->pszClipDstWhere);
1303 if( psOptionsIn->pszZField ) psOptions->pszZField = CPLStrdup(psOptionsIn->pszZField);
1304 if( psOptionsIn->pszSpatSRSDef ) psOptions->pszSpatSRSDef = CPLStrdup(psOptionsIn->pszSpatSRSDef);
1305 psOptions->papszSelFields = CSLDuplicate(psOptionsIn->papszSelFields);
1306 psOptions->papszFieldMap = CSLDuplicate(psOptionsIn->papszFieldMap);
1307 psOptions->papszMapFieldType = CSLDuplicate(psOptionsIn->papszMapFieldType);
1308 psOptions->papszLayers = CSLDuplicate(psOptionsIn->papszLayers);
1309 psOptions->papszDSCO = CSLDuplicate(psOptionsIn->papszDSCO);
1310 psOptions->papszLCO = CSLDuplicate(psOptionsIn->papszLCO);
1311 psOptions->papszDestOpenOptions = CSLDuplicate(psOptionsIn->papszDestOpenOptions);
1312 psOptions->papszFieldTypesToString = CSLDuplicate(psOptionsIn->papszFieldTypesToString);
1313 psOptions->papszMetadataOptions = CSLDuplicate(psOptionsIn->papszMetadataOptions);
1314 if( psOptionsIn->nGCPCount )
1315 psOptions->pasGCPs = GDALDuplicateGCPs( psOptionsIn->nGCPCount, psOptionsIn->pasGCPs );
1316 psOptions->hClipSrc = ( psOptionsIn->hClipSrc != nullptr ) ? OGR_G_Clone(psOptionsIn->hClipSrc) : nullptr;
1317 psOptions->hClipDst = ( psOptionsIn->hClipDst != nullptr ) ? OGR_G_Clone(psOptionsIn->hClipDst) : nullptr;
1318 psOptions->hSpatialFilter = ( psOptionsIn->hSpatialFilter != nullptr ) ? OGR_G_Clone(psOptionsIn->hSpatialFilter) : nullptr;
1319
1320 return psOptions;
1321 }
1322
1323 class GDALVectorTranslateWrappedDataset: public GDALDataset
1324 {
1325 GDALDataset* m_poBase;
1326 OGRSpatialReference* m_poOutputSRS;
1327 bool m_bTransform;
1328
1329 std::vector<OGRLayer*> m_apoLayers;
1330 std::vector<OGRLayer*> m_apoHiddenLayers;
1331
1332 GDALVectorTranslateWrappedDataset(
1333 GDALDataset* poBase,
1334 OGRSpatialReference* poOutputSRS,
1335 bool bTransform);
1336 public:
1337
1338 virtual ~GDALVectorTranslateWrappedDataset();
1339
GetLayerCount()1340 virtual int GetLayerCount() override
1341 { return static_cast<int>(m_apoLayers.size()); }
1342 virtual OGRLayer* GetLayer(int nIdx) override;
1343 virtual OGRLayer* GetLayerByName(const char* pszName) override;
1344
1345 virtual OGRLayer * ExecuteSQL( const char *pszStatement,
1346 OGRGeometry *poSpatialFilter,
1347 const char *pszDialect ) override;
1348 virtual void ReleaseResultSet( OGRLayer * poResultsSet ) override;
1349
1350 static GDALVectorTranslateWrappedDataset* New(
1351 GDALDataset* poBase,
1352 OGRSpatialReference* poOutputSRS,
1353 bool bTransform );
1354 };
1355
1356 class GDALVectorTranslateWrappedLayer: public OGRLayerDecorator
1357 {
1358 std::vector<OGRCoordinateTransformation*> m_apoCT;
1359 OGRFeatureDefn* m_poFDefn;
1360
1361 GDALVectorTranslateWrappedLayer(OGRLayer* poBaseLayer,
1362 bool bOwnBaseLayer);
1363 OGRFeature* TranslateFeature(OGRFeature* poSrcFeat);
1364 public:
1365
1366 virtual ~GDALVectorTranslateWrappedLayer();
GetLayerDefn()1367 virtual OGRFeatureDefn* GetLayerDefn() override { return m_poFDefn; }
1368 virtual OGRFeature* GetNextFeature() override;
1369 virtual OGRFeature* GetFeature(GIntBig nFID) override;
1370
1371 static GDALVectorTranslateWrappedLayer* New(
1372 OGRLayer* poBaseLayer,
1373 bool bOwnBaseLayer,
1374 OGRSpatialReference* poOutputSRS,
1375 bool bTransform);
1376 };
1377
GDALVectorTranslateWrappedLayer(OGRLayer * poBaseLayer,bool bOwnBaseLayer)1378 GDALVectorTranslateWrappedLayer::GDALVectorTranslateWrappedLayer(
1379 OGRLayer* poBaseLayer, bool bOwnBaseLayer) :
1380 OGRLayerDecorator(poBaseLayer, bOwnBaseLayer),
1381 m_apoCT( poBaseLayer->GetLayerDefn()->GetGeomFieldCount(),
1382 static_cast<OGRCoordinateTransformation*>(nullptr) ),
1383 m_poFDefn( nullptr )
1384 {
1385 }
1386
New(OGRLayer * poBaseLayer,bool bOwnBaseLayer,OGRSpatialReference * poOutputSRS,bool bTransform)1387 GDALVectorTranslateWrappedLayer* GDALVectorTranslateWrappedLayer::New(
1388 OGRLayer* poBaseLayer,
1389 bool bOwnBaseLayer,
1390 OGRSpatialReference* poOutputSRS,
1391 bool bTransform )
1392 {
1393 GDALVectorTranslateWrappedLayer* poNew =
1394 new GDALVectorTranslateWrappedLayer(poBaseLayer, bOwnBaseLayer);
1395 poNew->m_poFDefn = poBaseLayer->GetLayerDefn()->Clone();
1396 poNew->m_poFDefn->Reference();
1397 if( !poOutputSRS )
1398 return poNew;
1399
1400 for( int i=0; i < poNew->m_poFDefn->GetGeomFieldCount(); i++ )
1401 {
1402 if( bTransform )
1403 {
1404 OGRSpatialReference* poSourceSRS =
1405 poBaseLayer->GetLayerDefn()->
1406 GetGeomFieldDefn(i)->GetSpatialRef();
1407 if( poSourceSRS == nullptr )
1408 {
1409 CPLError(CE_Failure, CPLE_AppDefined,
1410 "Layer %s has no source SRS for geometry field %s",
1411 poBaseLayer->GetName(),
1412 poBaseLayer->GetLayerDefn()->
1413 GetGeomFieldDefn(i)->GetNameRef());
1414 delete poNew;
1415 return nullptr;
1416 }
1417 else
1418 {
1419 poNew->m_apoCT[i] = OGRCreateCoordinateTransformation(
1420 poSourceSRS,
1421 poOutputSRS);
1422 if( poNew->m_apoCT[i] == nullptr )
1423 {
1424 CPLError( CE_Failure, CPLE_AppDefined,
1425 "Failed to create coordinate transformation between the\n"
1426 "following coordinate systems. This may be because they\n"
1427 "are not transformable." );
1428
1429 char *pszWKT = nullptr;
1430 poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
1431 CPLError( CE_Failure, CPLE_AppDefined,
1432 "Source:\n%s", pszWKT );
1433 CPLFree(pszWKT);
1434
1435 poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
1436 CPLError( CE_Failure, CPLE_AppDefined,
1437 "Target:\n%s", pszWKT );
1438 CPLFree(pszWKT);
1439
1440 delete poNew;
1441 return nullptr;
1442 }
1443 }
1444 }
1445 poNew->m_poFDefn->GetGeomFieldDefn(i)->SetSpatialRef( poOutputSRS );
1446 }
1447
1448 return poNew;
1449 }
1450
~GDALVectorTranslateWrappedLayer()1451 GDALVectorTranslateWrappedLayer::~GDALVectorTranslateWrappedLayer()
1452 {
1453 if( m_poFDefn )
1454 m_poFDefn->Release();
1455 for( size_t i = 0; i < m_apoCT.size(); ++i )
1456 delete m_apoCT[i];
1457 }
1458
GetNextFeature()1459 OGRFeature* GDALVectorTranslateWrappedLayer::GetNextFeature()
1460 {
1461 return TranslateFeature(OGRLayerDecorator::GetNextFeature());
1462 }
1463
GetFeature(GIntBig nFID)1464 OGRFeature* GDALVectorTranslateWrappedLayer::GetFeature(GIntBig nFID)
1465 {
1466 return TranslateFeature(OGRLayerDecorator::GetFeature(nFID));
1467 }
1468
TranslateFeature(OGRFeature * poSrcFeat)1469 OGRFeature* GDALVectorTranslateWrappedLayer::TranslateFeature(
1470 OGRFeature* poSrcFeat )
1471 {
1472 if( poSrcFeat == nullptr )
1473 return nullptr;
1474 OGRFeature* poNewFeat = new OGRFeature(m_poFDefn);
1475 poNewFeat->SetFrom(poSrcFeat);
1476 poNewFeat->SetFID(poSrcFeat->GetFID());
1477 for( int i=0; i < poNewFeat->GetGeomFieldCount(); i++ )
1478 {
1479 OGRGeometry* poGeom = poNewFeat->GetGeomFieldRef(i);
1480 if( poGeom )
1481 {
1482 if( m_apoCT[i] )
1483 poGeom->transform( m_apoCT[i] );
1484 poGeom->assignSpatialReference(
1485 m_poFDefn->GetGeomFieldDefn(i)->GetSpatialRef() );
1486 }
1487 }
1488 delete poSrcFeat;
1489 return poNewFeat;
1490 }
1491
1492
GDALVectorTranslateWrappedDataset(GDALDataset * poBase,OGRSpatialReference * poOutputSRS,bool bTransform)1493 GDALVectorTranslateWrappedDataset::GDALVectorTranslateWrappedDataset(
1494 GDALDataset* poBase,
1495 OGRSpatialReference* poOutputSRS,
1496 bool bTransform):
1497 m_poBase(poBase),
1498 m_poOutputSRS(poOutputSRS),
1499 m_bTransform(bTransform)
1500 {
1501 SetDescription( poBase->GetDescription() );
1502 if( poBase->GetDriver() )
1503 {
1504 poDriver = new GDALDriver();
1505 poDriver->SetDescription( poBase->GetDriver()->GetDescription() );
1506 }
1507 }
1508
New(GDALDataset * poBase,OGRSpatialReference * poOutputSRS,bool bTransform)1509 GDALVectorTranslateWrappedDataset* GDALVectorTranslateWrappedDataset::New(
1510 GDALDataset* poBase,
1511 OGRSpatialReference* poOutputSRS,
1512 bool bTransform )
1513 {
1514 GDALVectorTranslateWrappedDataset* poNew =
1515 new GDALVectorTranslateWrappedDataset(
1516 poBase,
1517 poOutputSRS,
1518 bTransform);
1519 for(int i = 0; i < poBase->GetLayerCount(); i++ )
1520 {
1521 OGRLayer* poLayer = GDALVectorTranslateWrappedLayer::New(
1522 poBase->GetLayer(i), false, poOutputSRS, bTransform);
1523 if(poLayer == nullptr )
1524 {
1525 delete poNew;
1526 return nullptr;
1527 }
1528 poNew->m_apoLayers.push_back(poLayer);
1529 }
1530 return poNew;
1531 }
1532
~GDALVectorTranslateWrappedDataset()1533 GDALVectorTranslateWrappedDataset::~GDALVectorTranslateWrappedDataset()
1534 {
1535 delete poDriver;
1536 for(size_t i = 0; i < m_apoLayers.size(); i++ )
1537 {
1538 delete m_apoLayers[i];
1539 }
1540 for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
1541 {
1542 delete m_apoHiddenLayers[i];
1543 }
1544 }
1545
GetLayer(int i)1546 OGRLayer* GDALVectorTranslateWrappedDataset::GetLayer(int i)
1547 {
1548 if( i < 0 || i >= static_cast<int>(m_apoLayers.size()) )
1549 return nullptr;
1550 return m_apoLayers[i];
1551 }
1552
GetLayerByName(const char * pszName)1553 OGRLayer* GDALVectorTranslateWrappedDataset::GetLayerByName(const char* pszName)
1554 {
1555 for(size_t i = 0; i < m_apoLayers.size(); i++ )
1556 {
1557 if( strcmp(m_apoLayers[i]->GetName(), pszName) == 0 )
1558 return m_apoLayers[i];
1559 }
1560 for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
1561 {
1562 if( strcmp(m_apoHiddenLayers[i]->GetName(), pszName) == 0 )
1563 return m_apoHiddenLayers[i];
1564 }
1565 for(size_t i = 0; i < m_apoLayers.size(); i++ )
1566 {
1567 if( EQUAL(m_apoLayers[i]->GetName(), pszName) )
1568 return m_apoLayers[i];
1569 }
1570 for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
1571 {
1572 if( EQUAL(m_apoHiddenLayers[i]->GetName(), pszName) )
1573 return m_apoHiddenLayers[i];
1574 }
1575
1576 OGRLayer* poLayer = m_poBase->GetLayerByName(pszName);
1577 if( poLayer == nullptr )
1578 return nullptr;
1579 poLayer = GDALVectorTranslateWrappedLayer::New(
1580 poLayer, false, m_poOutputSRS, m_bTransform);
1581 if( poLayer == nullptr )
1582 return nullptr;
1583
1584 // Replicate source dataset behavior: if the fact of calling
1585 // GetLayerByName() on a initially hidden layer makes it visible through
1586 // GetLayerCount()/GetLayer(), do the same. Otherwise we are going to
1587 // maintain it hidden as well.
1588 for( int i = 0; i < m_poBase->GetLayerCount(); i++ )
1589 {
1590 if( m_poBase->GetLayer(i) == poLayer )
1591 {
1592 m_apoLayers.push_back(poLayer);
1593 return poLayer;
1594 }
1595 }
1596 m_apoHiddenLayers.push_back(poLayer);
1597 return poLayer;
1598 }
1599
1600
ExecuteSQL(const char * pszStatement,OGRGeometry * poSpatialFilter,const char * pszDialect)1601 OGRLayer * GDALVectorTranslateWrappedDataset::ExecuteSQL(
1602 const char *pszStatement,
1603 OGRGeometry *poSpatialFilter,
1604 const char *pszDialect )
1605 {
1606 OGRLayer* poLayer = m_poBase->ExecuteSQL(pszStatement,
1607 poSpatialFilter, pszDialect);
1608 if( poLayer == nullptr )
1609 return nullptr;
1610 return GDALVectorTranslateWrappedLayer::New(
1611 poLayer, true, m_poOutputSRS, m_bTransform);
1612 }
1613
ReleaseResultSet(OGRLayer * poResultsSet)1614 void GDALVectorTranslateWrappedDataset:: ReleaseResultSet(
1615 OGRLayer * poResultsSet )
1616 {
1617 delete poResultsSet;
1618 }
1619
1620 /************************************************************************/
1621 /* OGR2OGRSpatialReferenceHolder */
1622 /************************************************************************/
1623
1624 class OGR2OGRSpatialReferenceHolder
1625 {
1626 OGRSpatialReference* m_poSRS;
1627
1628 public:
OGR2OGRSpatialReferenceHolder()1629 OGR2OGRSpatialReferenceHolder() : m_poSRS(nullptr) {}
~OGR2OGRSpatialReferenceHolder()1630 ~OGR2OGRSpatialReferenceHolder() { if( m_poSRS) m_poSRS->Release(); }
1631
assignNoRefIncrease(OGRSpatialReference * poSRS)1632 void assignNoRefIncrease(OGRSpatialReference* poSRS) {
1633 CPLAssert(m_poSRS == nullptr);
1634 m_poSRS = poSRS;
1635 }
get()1636 OGRSpatialReference* get() { return m_poSRS; }
1637 };
1638
1639 /************************************************************************/
1640 /* GDALVectorTranslateCreateCopy() */
1641 /************************************************************************/
1642
GDALVectorTranslateCreateCopy(GDALDriver * poDriver,const char * pszDest,GDALDataset * poDS,const GDALVectorTranslateOptions * psOptions)1643 static GDALDataset* GDALVectorTranslateCreateCopy(
1644 GDALDriver* poDriver,
1645 const char* pszDest,
1646 GDALDataset* poDS,
1647 const GDALVectorTranslateOptions* psOptions)
1648 {
1649 const char* const szErrorMsg = "%s not supported by this output driver";
1650
1651 if( psOptions->bSkipFailures )
1652 {
1653 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-skipfailures");
1654 return nullptr;
1655 }
1656 if( psOptions->nLayerTransaction >= 0 )
1657 {
1658 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-lyr_transaction or -ds_transaction");
1659 return nullptr;
1660 }
1661 if( psOptions->nFIDToFetch >= 0 )
1662 {
1663 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fid");
1664 return nullptr;
1665 }
1666 if( psOptions->papszLCO )
1667 {
1668 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-lco");
1669 return nullptr;
1670 }
1671 if( psOptions->bAddMissingFields )
1672 {
1673 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-addfields");
1674 return nullptr;
1675 }
1676 if( psOptions->pszSourceSRSDef )
1677 {
1678 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-s_srs");
1679 return nullptr;
1680 }
1681 if( !psOptions->bExactFieldNameMatch )
1682 {
1683 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-relaxedFieldNameMatch");
1684 return nullptr;
1685 }
1686 if( psOptions->pszNewLayerName )
1687 {
1688 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nln");
1689 return nullptr;
1690 }
1691 if( psOptions->papszSelFields )
1692 {
1693 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-select");
1694 return nullptr;
1695 }
1696 if( psOptions->pszSQLStatement )
1697 {
1698 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-sql");
1699 return nullptr;
1700 }
1701 if( psOptions->pszDialect )
1702 {
1703 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-dialect");
1704 return nullptr;
1705 }
1706 if( psOptions->eGType != GEOMTYPE_UNCHANGED ||
1707 psOptions->eGeomTypeConversion != GTC_DEFAULT )
1708 {
1709 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nlt");
1710 return nullptr;
1711 }
1712 if( psOptions->papszFieldTypesToString )
1713 {
1714 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fieldTypeToString");
1715 return nullptr;
1716 }
1717 if( psOptions->papszMapFieldType )
1718 {
1719 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-mapFieldType");
1720 return nullptr;
1721 }
1722 if( psOptions->bUnsetFieldWidth )
1723 {
1724 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetFieldWidth");
1725 return nullptr;
1726 }
1727 if( psOptions->bWrapDateline )
1728 {
1729 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-wrapdateline");
1730 return nullptr;
1731 }
1732 if( psOptions->bClipSrc )
1733 {
1734 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrc");
1735 return nullptr;
1736 }
1737 if( psOptions->pszClipSrcSQL )
1738 {
1739 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrcsql");
1740 return nullptr;
1741 }
1742 if( psOptions->pszClipSrcLayer )
1743 {
1744 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrclayer");
1745 return nullptr;
1746 }
1747 if( psOptions->pszClipSrcWhere )
1748 {
1749 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrcwhere");
1750 return nullptr;
1751 }
1752 if( psOptions->pszClipDstDS || psOptions->hClipDst )
1753 {
1754 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdst");
1755 return nullptr;
1756 }
1757 if( psOptions->pszClipDstSQL )
1758 {
1759 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstsql");
1760 return nullptr;
1761 }
1762 if( psOptions->pszClipDstLayer )
1763 {
1764 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstlayer");
1765 return nullptr;
1766 }
1767 if( psOptions->pszClipDstWhere )
1768 {
1769 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstwhere");
1770 return nullptr;
1771 }
1772 if( psOptions->bSplitListFields )
1773 {
1774 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-splitlistfields");
1775 return nullptr;
1776 }
1777 if( psOptions->nMaxSplitListSubFields >= 0 )
1778 {
1779 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-maxsubfields");
1780 return nullptr;
1781 }
1782 if( psOptions->bExplodeCollections )
1783 {
1784 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-explodecollections");
1785 return nullptr;
1786 }
1787 if( psOptions->pszZField )
1788 {
1789 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-zfield");
1790 return nullptr;
1791 }
1792 if( psOptions->nGCPCount )
1793 {
1794 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-gcp");
1795 return nullptr;
1796 }
1797 if( psOptions->papszFieldMap )
1798 {
1799 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fieldmap");
1800 return nullptr;
1801 }
1802 if( psOptions->bForceNullable )
1803 {
1804 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-forceNullable");
1805 return nullptr;
1806 }
1807 if( psOptions->bResolveDomains )
1808 {
1809 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-forceNullable");
1810 return nullptr;
1811 }
1812 if( psOptions->bEmptyStrAsNull )
1813 {
1814 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-emptyStrAsNull");
1815 return nullptr;
1816 }
1817 if( psOptions->bUnsetDefault )
1818 {
1819 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetDefault");
1820 return nullptr;
1821 }
1822 if( psOptions->bUnsetFid )
1823 {
1824 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetFid");
1825 return nullptr;
1826 }
1827 if( !psOptions->bCopyMD )
1828 {
1829 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nomd");
1830 return nullptr;
1831 }
1832 if( !psOptions->bNativeData )
1833 {
1834 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-noNativeData");
1835 return nullptr;
1836 }
1837 if( psOptions->nLimit >= 0 )
1838 {
1839 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-limit");
1840 return nullptr;
1841 }
1842 if( psOptions->papszMetadataOptions )
1843 {
1844 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-mo");
1845 return nullptr;
1846 }
1847
1848 GDALDataset* poWrkSrcDS = poDS;
1849 OGR2OGRSpatialReferenceHolder oOutputSRSHolder;
1850
1851 if( psOptions->pszOutputSRSDef )
1852 {
1853 oOutputSRSHolder.assignNoRefIncrease(new OGRSpatialReference());
1854 oOutputSRSHolder.get()->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
1855 if( oOutputSRSHolder.get()->
1856 SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
1857 {
1858 CPLError( CE_Failure, CPLE_AppDefined,
1859 "Failed to process SRS definition: %s",
1860 psOptions->pszOutputSRSDef );
1861 return nullptr;
1862 }
1863 poWrkSrcDS = GDALVectorTranslateWrappedDataset::New(
1864 poDS, oOutputSRSHolder.get(), psOptions->bTransform);
1865 if( poWrkSrcDS == nullptr )
1866 return nullptr;
1867 }
1868
1869 if( psOptions->pszWHERE )
1870 {
1871 // Hack for GMLAS driver
1872 if( EQUAL(poDriver->GetDescription(), "GMLAS") )
1873 {
1874 if( psOptions->papszLayers == nullptr )
1875 {
1876 CPLError(CE_Failure, CPLE_NotSupported,
1877 "-where not supported by this output driver "
1878 "without explicit layer name(s)");
1879 if( poWrkSrcDS != poDS )
1880 delete poWrkSrcDS;
1881 return nullptr;
1882 }
1883 else
1884 {
1885 char** papszIter = psOptions->papszLayers;
1886 for( ; *papszIter != nullptr; ++papszIter )
1887 {
1888 OGRLayer* poSrcLayer = poDS->GetLayerByName(*papszIter);
1889 if( poSrcLayer != nullptr )
1890 {
1891 poSrcLayer->SetAttributeFilter( psOptions->pszWHERE );
1892 }
1893 }
1894 }
1895 }
1896 else
1897 {
1898 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-where");
1899 if( poWrkSrcDS != poDS )
1900 delete poWrkSrcDS;
1901 return nullptr;
1902 }
1903 }
1904
1905 if( psOptions->hSpatialFilter )
1906 {
1907 for( int i=0; i<poWrkSrcDS->GetLayerCount();++i)
1908 {
1909 OGRLayer* poSrcLayer = poWrkSrcDS->GetLayer(i);
1910 if( poSrcLayer &&
1911 poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 &&
1912 (psOptions->papszLayers == nullptr ||
1913 CSLFindString(psOptions->papszLayers,
1914 poSrcLayer->GetName())>=0) )
1915 {
1916 if( psOptions->pszGeomField != nullptr )
1917 {
1918 const int iGeomField = poSrcLayer->GetLayerDefn()->
1919 GetGeomFieldIndex(psOptions->pszGeomField);
1920 if( iGeomField >= 0 )
1921 poSrcLayer->SetSpatialFilter( iGeomField,
1922 reinterpret_cast<OGRGeometry*>(
1923 psOptions->hSpatialFilter) );
1924 else
1925 CPLError( CE_Warning, CPLE_AppDefined,
1926 "Cannot find geometry field %s in layer %s. "
1927 "Applying to first geometry field",
1928 psOptions->pszGeomField,
1929 poSrcLayer->GetName() );
1930 }
1931 else
1932 {
1933 poSrcLayer->SetSpatialFilter(
1934 reinterpret_cast<OGRGeometry*>(
1935 psOptions->hSpatialFilter) );
1936 }
1937 }
1938 }
1939 }
1940
1941 char** papszDSCO = CSLDuplicate(psOptions->papszDSCO);
1942 if( psOptions->papszLayers )
1943 {
1944 // Hack for GMLAS driver
1945 if( EQUAL(poDriver->GetDescription(), "GMLAS") )
1946 {
1947 CPLString osLayers;
1948 char** papszIter = psOptions->papszLayers;
1949 for( ; *papszIter != nullptr; ++papszIter )
1950 {
1951 if( !osLayers.empty() )
1952 osLayers += ",";
1953 osLayers += *papszIter;
1954 }
1955 papszDSCO = CSLSetNameValue(papszDSCO, "LAYERS", osLayers);
1956 }
1957 else
1958 {
1959 CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg,
1960 "Specifying layers");
1961 CSLDestroy(papszDSCO);
1962 if( poWrkSrcDS != poDS )
1963 delete poWrkSrcDS;
1964 return nullptr;
1965 }
1966 }
1967
1968 // Hack for GMLAS driver (this speed up deletion by avoiding the GML
1969 // driver to try parsing a pre-existing file). Could be potentially
1970 // removed if the GML driver implemented fast dataset opening (ie
1971 // without parsing) and GetFileList()
1972 if( EQUAL(poDriver->GetDescription(), "GMLAS") )
1973 {
1974 GDALDriverH hIdentifyingDriver = GDALIdentifyDriver(pszDest, nullptr);
1975 if( hIdentifyingDriver != nullptr &&
1976 EQUAL( GDALGetDescription(hIdentifyingDriver), "GML" ) )
1977 {
1978 VSIUnlink( pszDest );
1979 VSIUnlink( CPLResetExtension(pszDest, "gfs") );
1980 }
1981 }
1982
1983 GDALDataset* poOut = poDriver->CreateCopy(pszDest, poWrkSrcDS, FALSE,
1984 papszDSCO,
1985 psOptions->pfnProgress,
1986 psOptions->pProgressData);
1987 CSLDestroy(papszDSCO);
1988
1989 if( poWrkSrcDS != poDS )
1990 delete poWrkSrcDS;
1991
1992 return poOut;
1993 }
1994
1995 /************************************************************************/
1996 /* GDALVectorTranslate() */
1997 /************************************************************************/
1998 /**
1999 * Converts vector data between file formats.
2000 *
2001 * This is the equivalent of the <a href="/programs/ogr2ogr.html">ogr2ogr</a> utility.
2002 *
2003 * GDALVectorTranslateOptions* must be allocated and freed with GDALVectorTranslateOptionsNew()
2004 * and GDALVectorTranslateOptionsFree() respectively.
2005 * pszDest and hDstDS cannot be used at the same time.
2006 *
2007 * @param pszDest the destination dataset path or NULL.
2008 * @param hDstDS the destination dataset or NULL.
2009 * @param nSrcCount the number of input datasets (only 1 supported currently)
2010 * @param pahSrcDS the list of input datasets.
2011 * @param psOptionsIn the options struct returned by GDALVectorTranslateOptionsNew() or NULL.
2012 * @param pbUsageError pointer to a integer output variable to store if any usage error has occurred, or NULL.
2013 * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
2014 *
2015 * @since GDAL 2.1
2016 */
2017
GDALVectorTranslate(const char * pszDest,GDALDatasetH hDstDS,int nSrcCount,GDALDatasetH * pahSrcDS,const GDALVectorTranslateOptions * psOptionsIn,int * pbUsageError)2018 GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
2019 GDALDatasetH *pahSrcDS,
2020 const GDALVectorTranslateOptions *psOptionsIn, int *pbUsageError )
2021
2022 {
2023 if( pszDest == nullptr && hDstDS == nullptr )
2024 {
2025 CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");
2026
2027 if(pbUsageError)
2028 *pbUsageError = TRUE;
2029 return nullptr;
2030 }
2031 if( nSrcCount != 1 )
2032 {
2033 CPLError( CE_Failure, CPLE_AppDefined, "nSrcCount != 1");
2034
2035 if(pbUsageError)
2036 *pbUsageError = TRUE;
2037 return nullptr;
2038 }
2039
2040 GDALDatasetH hSrcDS = pahSrcDS[0];
2041 if( hSrcDS == nullptr )
2042 {
2043 CPLError( CE_Failure, CPLE_AppDefined, "hSrcDS == NULL");
2044
2045 if(pbUsageError)
2046 *pbUsageError = TRUE;
2047 return nullptr;
2048 }
2049
2050 GDALVectorTranslateOptions* psOptions =
2051 psOptionsIn
2052 ? GDALVectorTranslateOptionsClone(psOptionsIn)
2053 : GDALVectorTranslateOptionsNew(nullptr, nullptr);
2054
2055 bool bAppend = false;
2056 bool bUpdate = false;
2057 bool bOverwrite = false;
2058
2059 if( psOptions->eAccessMode == ACCESS_UPDATE )
2060 {
2061 bUpdate = true;
2062 }
2063 else if ( psOptions->eAccessMode == ACCESS_APPEND )
2064 {
2065 bAppend = true;
2066 bUpdate = true;
2067 }
2068 else if ( psOptions->eAccessMode == ACCESS_OVERWRITE )
2069 {
2070 bOverwrite = true;
2071 bUpdate = true;
2072 }
2073 else if( hDstDS != nullptr )
2074 {
2075 bUpdate = true;
2076 }
2077
2078 const CPLString osDateLineOffset =
2079 CPLOPrintf("%g", psOptions->dfDateLineOffset);
2080
2081 if( psOptions->bPreserveFID && psOptions->bExplodeCollections )
2082 {
2083 CPLError( CE_Failure, CPLE_IllegalArg, "cannot use -preserve_fid and -explodecollections at the same time.");
2084 if(pbUsageError)
2085 *pbUsageError = TRUE;
2086 GDALVectorTranslateOptionsFree(psOptions);
2087 return nullptr;
2088 }
2089
2090 if (psOptions->papszFieldMap && !bAppend)
2091 {
2092 CPLError( CE_Failure, CPLE_IllegalArg, "if -fieldmap is specified, -append must also be specified");
2093 if(pbUsageError)
2094 *pbUsageError = TRUE;
2095 GDALVectorTranslateOptionsFree(psOptions);
2096 return nullptr;
2097 }
2098
2099 if (psOptions->papszFieldMap && psOptions->bAddMissingFields)
2100 {
2101 CPLError( CE_Failure, CPLE_IllegalArg, "if -addfields is specified, -fieldmap cannot be used.");
2102 if(pbUsageError)
2103 *pbUsageError = TRUE;
2104 GDALVectorTranslateOptionsFree(psOptions);
2105 return nullptr;
2106 }
2107
2108 if (psOptions->papszSelFields && bAppend && !psOptions->bAddMissingFields)
2109 {
2110 CPLError( CE_Failure, CPLE_IllegalArg, "if -append is specified, -select cannot be used "
2111 "(use -fieldmap or -sql instead)." );
2112 if(pbUsageError)
2113 *pbUsageError = TRUE;
2114 GDALVectorTranslateOptionsFree(psOptions);
2115 return nullptr;
2116 }
2117
2118 if( psOptions->papszFieldTypesToString && psOptions->papszMapFieldType )
2119 {
2120 CPLError( CE_Failure, CPLE_IllegalArg, "-fieldTypeToString and -mapFieldType are exclusive.");
2121 if(pbUsageError)
2122 *pbUsageError = TRUE;
2123 GDALVectorTranslateOptionsFree(psOptions);
2124 return nullptr;
2125 }
2126
2127 if( psOptions->pszSourceSRSDef != nullptr && psOptions->pszOutputSRSDef == nullptr && psOptions->pszSpatSRSDef == nullptr )
2128 {
2129 CPLError( CE_Failure, CPLE_IllegalArg, "if -s_srs is specified, -t_srs and/or -spat_srs must also be specified.");
2130 if(pbUsageError)
2131 *pbUsageError = TRUE;
2132 GDALVectorTranslateOptionsFree(psOptions);
2133 return nullptr;
2134 }
2135
2136 if( psOptions->bClipSrc && psOptions->pszClipSrcDS != nullptr)
2137 {
2138 psOptions->hClipSrc = reinterpret_cast<OGRGeometryH>(LoadGeometry(psOptions->pszClipSrcDS, psOptions->pszClipSrcSQL, psOptions->pszClipSrcLayer, psOptions->pszClipSrcWhere));
2139 if (psOptions->hClipSrc == nullptr)
2140 {
2141 CPLError( CE_Failure,CPLE_IllegalArg, "cannot load source clip geometry");
2142 GDALVectorTranslateOptionsFree(psOptions);
2143 return nullptr;
2144 }
2145 }
2146 else if( psOptions->bClipSrc && psOptions->hClipSrc == nullptr )
2147 {
2148 if (psOptions->hSpatialFilter)
2149 psOptions->hClipSrc = OGR_G_Clone(psOptions->hSpatialFilter);
2150 if (psOptions->hClipSrc == nullptr)
2151 {
2152 CPLError( CE_Failure, CPLE_IllegalArg, "-clipsrc must be used with -spat option or a\n"
2153 "bounding box, WKT string or datasource must be specified");
2154 if(pbUsageError)
2155 *pbUsageError = TRUE;
2156 GDALVectorTranslateOptionsFree(psOptions);
2157 return nullptr;
2158 }
2159 }
2160
2161 if( psOptions->pszClipDstDS != nullptr)
2162 {
2163 psOptions->hClipDst = reinterpret_cast<OGRGeometryH>(LoadGeometry(psOptions->pszClipDstDS, psOptions->pszClipDstSQL, psOptions->pszClipDstLayer, psOptions->pszClipDstWhere));
2164 if (psOptions->hClipDst == nullptr)
2165 {
2166 CPLError( CE_Failure, CPLE_IllegalArg, "cannot load dest clip geometry");
2167 GDALVectorTranslateOptionsFree(psOptions);
2168 return nullptr;
2169 }
2170 }
2171
2172 GDALDataset *poDS = static_cast<GDALDataset *>(hSrcDS);
2173 GDALDataset *poODS = nullptr;
2174 GDALDriver *poDriver = nullptr;
2175 CPLString osDestFilename;
2176
2177 if(hDstDS)
2178 {
2179 poODS = static_cast<GDALDataset *>(hDstDS);
2180 osDestFilename = poODS->GetDescription();
2181 }
2182 else
2183 {
2184 osDestFilename = pszDest;
2185 }
2186
2187 /* Various tests to avoid overwriting the source layer(s) */
2188 /* or to avoid appending a layer to itself */
2189 if( bUpdate && strcmp(osDestFilename, poDS->GetDescription()) == 0 &&
2190 !EQUAL(poDS->GetDriverName(), "Memory") &&
2191 (bOverwrite || bAppend) )
2192 {
2193 bool bError = false;
2194 if (psOptions->pszNewLayerName == nullptr)
2195 bError = true;
2196 else if (CSLCount(psOptions->papszLayers) == 1)
2197 bError = strcmp(psOptions->pszNewLayerName, psOptions->papszLayers[0]) == 0;
2198 else if (psOptions->pszSQLStatement == nullptr)
2199 bError = true;
2200 if (bError)
2201 {
2202 CPLError( CE_Failure, CPLE_IllegalArg,
2203 "-nln name must be specified combined with "
2204 "a single source layer name,\nor a -sql statement, and "
2205 "name must be different from an existing layer.");
2206 GDALVectorTranslateOptionsFree(psOptions);
2207 return nullptr;
2208 }
2209 }
2210 else if( !bUpdate && strcmp(osDestFilename, poDS->GetDescription()) == 0 &&
2211 (psOptions->pszFormat == nullptr || !EQUAL(psOptions->pszFormat, "Memory")) )
2212 {
2213 CPLError( CE_Failure, CPLE_AppDefined,
2214 "Source and destination datasets must be different "
2215 "in non-update mode." );
2216 GDALVectorTranslateOptionsFree(psOptions);
2217 return nullptr;
2218 }
2219
2220 /* -------------------------------------------------------------------- */
2221 /* Try opening the output datasource as an existing, writable */
2222 /* -------------------------------------------------------------------- */
2223 std::vector<CPLString> aoDrivers;
2224 if( poODS == nullptr && psOptions->pszFormat == nullptr )
2225 {
2226 aoDrivers = GetOutputDriversFor(pszDest, GDAL_OF_VECTOR);
2227 if( !bUpdate && aoDrivers.size() == 1 )
2228 {
2229 GDALDriverH hDriver = GDALGetDriverByName(aoDrivers[0]);
2230 const char* pszPrefix = GDALGetMetadataItem(hDriver,
2231 GDAL_DMD_CONNECTION_PREFIX, nullptr);
2232 if( pszPrefix && STARTS_WITH_CI(pszDest, pszPrefix) )
2233 {
2234 bUpdate = true;
2235 }
2236 }
2237 }
2238
2239 if( bUpdate && poODS == nullptr )
2240 {
2241 poODS = static_cast<GDALDataset*>(GDALOpenEx( osDestFilename,
2242 GDAL_OF_UPDATE | GDAL_OF_VECTOR, nullptr, psOptions->papszDestOpenOptions, nullptr ));
2243
2244 if( poODS == nullptr )
2245 {
2246 if (bOverwrite || bAppend)
2247 {
2248 poODS = static_cast<GDALDataset*>(GDALOpenEx( osDestFilename,
2249 GDAL_OF_VECTOR, nullptr, psOptions->papszDestOpenOptions, nullptr ));
2250 if (poODS == nullptr)
2251 {
2252 /* OK the datasource doesn't exist at all */
2253 bUpdate = false;
2254 }
2255 else
2256 {
2257 poDriver = poODS->GetDriver();
2258 GDALClose(poODS);
2259 poODS = nullptr;
2260 }
2261 }
2262
2263 if (bUpdate)
2264 {
2265 CPLError( CE_Failure, CPLE_AppDefined,
2266 "Unable to open existing output datasource `%s'.",
2267 osDestFilename.c_str() );
2268 GDALVectorTranslateOptionsFree(psOptions);
2269 return nullptr;
2270 }
2271 }
2272 else if( CSLCount(psOptions->papszDSCO) > 0 )
2273 {
2274 CPLError( CE_Warning, CPLE_AppDefined, "Datasource creation options ignored since an existing datasource\n"
2275 " being updated." );
2276 }
2277 }
2278
2279 if( poODS )
2280 poDriver = poODS->GetDriver();
2281
2282 /* -------------------------------------------------------------------- */
2283 /* Find the output driver. */
2284 /* -------------------------------------------------------------------- */
2285 bool bNewDataSource = false;
2286 if( !bUpdate )
2287 {
2288 GDALDriverManager *poDM = GetGDALDriverManager();
2289
2290 if( psOptions->pszFormat == nullptr )
2291 {
2292 if( aoDrivers.empty() )
2293 {
2294 if( EQUAL(CPLGetExtension(pszDest), "") )
2295 {
2296 psOptions->pszFormat = CPLStrdup("ESRI Shapefile");
2297 }
2298 else
2299 {
2300 CPLError( CE_Failure, CPLE_AppDefined,
2301 "Cannot guess driver for %s", pszDest);
2302 GDALVectorTranslateOptionsFree(psOptions);
2303 return nullptr;
2304 }
2305 }
2306 else
2307 {
2308 if( aoDrivers.size() > 1 )
2309 {
2310 CPLError( CE_Warning, CPLE_AppDefined,
2311 "Several drivers matching %s extension. Using %s",
2312 CPLGetExtension(pszDest), aoDrivers[0].c_str() );
2313 }
2314 psOptions->pszFormat = CPLStrdup(aoDrivers[0]);
2315 }
2316 CPLDebug("GDAL", "Using %s driver",
2317 psOptions->pszFormat);
2318 }
2319
2320 CPLString osOGRCompatFormat(psOptions->pszFormat);
2321 // Special processing for non-unified drivers that have the same name
2322 // as GDAL and OGR drivers. GMT should become OGR_GMT.
2323 // Other candidates could be VRT, SDTS and PDS, but they don't
2324 // have write capabilities. But do the substitution to get a sensible
2325 // error message
2326 if( EQUAL(osOGRCompatFormat, "GMT") ||
2327 EQUAL(osOGRCompatFormat, "VRT") ||
2328 EQUAL(osOGRCompatFormat, "SDTS") ||
2329 EQUAL(osOGRCompatFormat, "PDS") )
2330 {
2331 osOGRCompatFormat = "OGR_" + osOGRCompatFormat;
2332 }
2333 poDriver = poDM->GetDriverByName(osOGRCompatFormat);
2334 if( poDriver == nullptr )
2335 {
2336 CPLError( CE_Failure, CPLE_AppDefined,
2337 "Unable to find driver `%s'.", psOptions->pszFormat );
2338 GDALVectorTranslateOptionsFree(psOptions);
2339 return nullptr;
2340 }
2341
2342 char** papszDriverMD = poDriver->GetMetadata();
2343 if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
2344 GDAL_DCAP_VECTOR, "FALSE") ) )
2345 {
2346 CPLError( CE_Failure, CPLE_AppDefined,
2347 "%s driver has no vector capabilities.",
2348 psOptions->pszFormat );
2349 GDALVectorTranslateOptionsFree(psOptions);
2350 return nullptr;
2351 }
2352
2353 if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
2354 GDAL_DCAP_CREATE, "FALSE") ) )
2355 {
2356 if( CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
2357 GDAL_DCAP_CREATECOPY, "FALSE") ) )
2358 {
2359 poODS = GDALVectorTranslateCreateCopy(poDriver, pszDest,
2360 poDS, psOptions);
2361 GDALVectorTranslateOptionsFree(psOptions);
2362 return poODS;
2363 }
2364
2365 CPLError( CE_Failure, CPLE_AppDefined,
2366 "%s driver does not support data source creation.",
2367 psOptions->pszFormat );
2368 GDALVectorTranslateOptionsFree(psOptions);
2369 return nullptr;
2370 }
2371
2372 if( psOptions->papszDestOpenOptions != nullptr )
2373 {
2374 CPLError(CE_Warning, CPLE_AppDefined, "-doo ignored when creating the output datasource.");
2375 }
2376
2377 /* -------------------------------------------------------------------- */
2378 /* Special case to improve user experience when translating */
2379 /* a datasource with multiple layers into a shapefile. If the */
2380 /* user gives a target datasource with .shp and it does not exist, */
2381 /* the shapefile driver will try to create a file, but this is not */
2382 /* appropriate because here we have several layers, so create */
2383 /* a directory instead. */
2384 /* -------------------------------------------------------------------- */
2385 VSIStatBufL sStat;
2386 if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
2387 psOptions->pszSQLStatement == nullptr &&
2388 (CSLCount(psOptions->papszLayers) > 1 ||
2389 (CSLCount(psOptions->papszLayers) == 0 && poDS->GetLayerCount() > 1)) &&
2390 psOptions->pszNewLayerName == nullptr &&
2391 EQUAL(CPLGetExtension(osDestFilename), "SHP") &&
2392 VSIStatL(osDestFilename, &sStat) != 0)
2393 {
2394 if (VSIMkdir(osDestFilename, 0755) != 0)
2395 {
2396 CPLError( CE_Failure, CPLE_AppDefined,
2397 "Failed to create directory %s\n"
2398 "for shapefile datastore.",
2399 osDestFilename.c_str() );
2400 GDALVectorTranslateOptionsFree(psOptions);
2401 return nullptr;
2402 }
2403 }
2404
2405 /* -------------------------------------------------------------------- */
2406 /* Create the output data source. */
2407 /* -------------------------------------------------------------------- */
2408 poODS = poDriver->Create( osDestFilename, 0, 0, 0, GDT_Unknown, psOptions->papszDSCO );
2409 if( poODS == nullptr )
2410 {
2411 CPLError( CE_Failure, CPLE_AppDefined, "%s driver failed to create %s",
2412 psOptions->pszFormat, osDestFilename.c_str() );
2413 GDALVectorTranslateOptionsFree(psOptions);
2414 return nullptr;
2415 }
2416 bNewDataSource = true;
2417
2418 if( psOptions->bCopyMD )
2419 {
2420 char** papszDomains = poDS->GetMetadataDomainList();
2421 for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
2422 {
2423 char** papszMD = poDS->GetMetadata(*papszIter);
2424 if( papszMD )
2425 poODS->SetMetadata(papszMD, *papszIter);
2426 }
2427 CSLDestroy(papszDomains);
2428 }
2429 for(char** papszIter = psOptions->papszMetadataOptions; papszIter && *papszIter; ++papszIter )
2430 {
2431 char *pszKey = nullptr;
2432 const char *pszValue = CPLParseNameValue( *papszIter, &pszKey );
2433 if( pszKey )
2434 {
2435 poODS->SetMetadataItem(pszKey,pszValue);
2436 CPLFree( pszKey );
2437 }
2438 }
2439 }
2440
2441 /* -------------------------------------------------------------------- */
2442 /* For random reading */
2443 /* -------------------------------------------------------------------- */
2444 const bool bRandomLayerReading = CPL_TO_BOOL(
2445 poDS->TestCapability(ODsCRandomLayerRead));
2446 if( bRandomLayerReading &&
2447 !poODS->TestCapability(ODsCRandomLayerWrite) &&
2448 CSLCount(psOptions->papszLayers) != 1 &&
2449 psOptions->pszSQLStatement == nullptr &&
2450 !psOptions->bQuiet )
2451 {
2452 CPLError(CE_Warning, CPLE_AppDefined,
2453 "Input datasource uses random layer reading, but "
2454 "output datasource does not support random layer writing");
2455 }
2456
2457 if( psOptions->nLayerTransaction < 0 )
2458 {
2459 if( bRandomLayerReading )
2460 psOptions->nLayerTransaction = FALSE;
2461 else
2462 psOptions->nLayerTransaction = !poODS->TestCapability(ODsCTransactions);
2463 }
2464 else if( psOptions->nLayerTransaction &&
2465 bRandomLayerReading )
2466 {
2467 psOptions->nLayerTransaction = false;
2468 }
2469
2470 /* -------------------------------------------------------------------- */
2471 /* Parse the output SRS definition if possible. */
2472 /* -------------------------------------------------------------------- */
2473 OGR2OGRSpatialReferenceHolder oOutputSRSHolder;
2474 if( psOptions->pszOutputSRSDef != nullptr )
2475 {
2476 oOutputSRSHolder.assignNoRefIncrease(new OGRSpatialReference());
2477 oOutputSRSHolder.get()->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2478 if( oOutputSRSHolder.get()->
2479 SetFromUserInput( psOptions->pszOutputSRSDef ) != OGRERR_NONE )
2480 {
2481 CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
2482 psOptions->pszOutputSRSDef );
2483 GDALVectorTranslateOptionsFree(psOptions);
2484 if( hDstDS == nullptr ) GDALClose( poODS );
2485 return nullptr;
2486 }
2487 }
2488
2489 /* -------------------------------------------------------------------- */
2490 /* Parse the source SRS definition if possible. */
2491 /* -------------------------------------------------------------------- */
2492 OGRSpatialReference oSourceSRS;
2493 OGRSpatialReference *poSourceSRS = nullptr;
2494 if( psOptions->pszSourceSRSDef != nullptr )
2495 {
2496 oSourceSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2497 if( oSourceSRS.SetFromUserInput( psOptions->pszSourceSRSDef ) != OGRERR_NONE )
2498 {
2499 CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
2500 psOptions->pszSourceSRSDef );
2501 GDALVectorTranslateOptionsFree(psOptions);
2502 if( hDstDS == nullptr ) GDALClose( poODS );
2503 return nullptr;
2504 }
2505 poSourceSRS = &oSourceSRS;
2506 }
2507
2508 /* -------------------------------------------------------------------- */
2509 /* Parse spatial filter SRS if needed. */
2510 /* -------------------------------------------------------------------- */
2511 OGRSpatialReference oSpatSRS;
2512 OGRSpatialReference* poSpatSRS = nullptr;
2513 if( psOptions->hSpatialFilter != nullptr && psOptions->pszSpatSRSDef != nullptr )
2514 {
2515 if( psOptions->pszSQLStatement )
2516 {
2517 CPLError( CE_Failure, CPLE_IllegalArg, "-spat_srs not compatible with -sql.");
2518 GDALVectorTranslateOptionsFree(psOptions);
2519 if( hDstDS == nullptr ) GDALClose( poODS );
2520 return nullptr;
2521 }
2522 OGREnvelope sEnvelope;
2523 OGR_G_GetEnvelope(psOptions->hSpatialFilter, &sEnvelope);
2524 oSpatSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2525 if( oSpatSRS.SetFromUserInput( psOptions->pszSpatSRSDef ) != OGRERR_NONE )
2526 {
2527 CPLError( CE_Failure, CPLE_AppDefined, "Failed to process SRS definition: %s",
2528 psOptions->pszSpatSRSDef );
2529 GDALVectorTranslateOptionsFree(psOptions);
2530 if( hDstDS == nullptr ) GDALClose( poODS );
2531 return nullptr;
2532 }
2533 poSpatSRS = &oSpatSRS;
2534 }
2535
2536 /* -------------------------------------------------------------------- */
2537 /* Create a transformation object from the source to */
2538 /* destination coordinate system. */
2539 /* -------------------------------------------------------------------- */
2540 GCPCoordTransformation *poGCPCoordTrans = nullptr;
2541 if( psOptions->nGCPCount > 0 )
2542 {
2543 poGCPCoordTrans = new GCPCoordTransformation( psOptions->nGCPCount, psOptions->pasGCPs,
2544 psOptions->nTransformOrder,
2545 poSourceSRS ? poSourceSRS : oOutputSRSHolder.get() );
2546 if( !(poGCPCoordTrans->IsValid()) )
2547 {
2548 delete poGCPCoordTrans;
2549 poGCPCoordTrans = nullptr;
2550 }
2551 }
2552
2553 /* -------------------------------------------------------------------- */
2554 /* Create layer setup and transformer objects. */
2555 /* -------------------------------------------------------------------- */
2556 SetupTargetLayer oSetup;
2557 oSetup.m_poSrcDS = poDS;
2558 oSetup.m_poDstDS = poODS;
2559 oSetup.m_papszLCO = psOptions->papszLCO;
2560 oSetup.m_poOutputSRS = oOutputSRSHolder.get();
2561 oSetup.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
2562 oSetup.m_papszSelFields = psOptions->papszSelFields;
2563 oSetup.m_bAppend = bAppend;
2564 oSetup.m_bAddMissingFields = psOptions->bAddMissingFields;
2565 oSetup.m_eGType = psOptions->eGType;
2566 oSetup.m_eGeomTypeConversion = psOptions->eGeomTypeConversion;
2567 oSetup.m_nCoordDim = psOptions->nCoordDim;
2568 oSetup.m_bOverwrite = bOverwrite;
2569 oSetup.m_papszFieldTypesToString = psOptions->papszFieldTypesToString;
2570 oSetup.m_papszMapFieldType = psOptions->papszMapFieldType;
2571 oSetup.m_bUnsetFieldWidth = psOptions->bUnsetFieldWidth;
2572 oSetup.m_bExplodeCollections = psOptions->bExplodeCollections;
2573 oSetup.m_pszZField = psOptions->pszZField;
2574 oSetup.m_papszFieldMap = psOptions->papszFieldMap;
2575 oSetup.m_pszWHERE = psOptions->pszWHERE;
2576 oSetup.m_bExactFieldNameMatch = psOptions->bExactFieldNameMatch;
2577 oSetup.m_bQuiet = psOptions->bQuiet;
2578 oSetup.m_bForceNullable = psOptions->bForceNullable;
2579 oSetup.m_bResolveDomains = psOptions->bResolveDomains;
2580 oSetup.m_bUnsetDefault = psOptions->bUnsetDefault;
2581 oSetup.m_bUnsetFid = psOptions->bUnsetFid;
2582 oSetup.m_bPreserveFID = psOptions->bPreserveFID;
2583 oSetup.m_bCopyMD = psOptions->bCopyMD;
2584 oSetup.m_bNativeData = psOptions->bNativeData;
2585 oSetup.m_bNewDataSource = bNewDataSource;
2586 oSetup.m_pszCTPipeline = psOptions->pszCTPipeline;
2587
2588 LayerTranslator oTranslator;
2589 oTranslator.m_poSrcDS = poDS;
2590 oTranslator.m_poODS = poODS;
2591 oTranslator.m_bTransform = psOptions->bTransform;
2592 oTranslator.m_bWrapDateline = psOptions->bWrapDateline;
2593 oTranslator.m_osDateLineOffset = osDateLineOffset;
2594 oTranslator.m_poOutputSRS = oOutputSRSHolder.get();
2595 oTranslator.m_bNullifyOutputSRS = psOptions->bNullifyOutputSRS;
2596 oTranslator.m_poUserSourceSRS = poSourceSRS;
2597 oTranslator.m_poGCPCoordTrans = poGCPCoordTrans;
2598 oTranslator.m_eGType = psOptions->eGType;
2599 oTranslator.m_eGeomTypeConversion = psOptions->eGeomTypeConversion;
2600 oTranslator.m_bMakeValid = psOptions->bMakeValid;
2601 oTranslator.m_nCoordDim = psOptions->nCoordDim;
2602 oTranslator.m_eGeomOp = psOptions->eGeomOp;
2603 oTranslator.m_dfGeomOpParam = psOptions->dfGeomOpParam;
2604 oTranslator.m_poClipSrc = reinterpret_cast<OGRGeometry*>(psOptions->hClipSrc);
2605 oTranslator.m_poClipDst = reinterpret_cast<OGRGeometry*>(psOptions->hClipDst);
2606 oTranslator.m_bExplodeCollections = psOptions->bExplodeCollections;
2607 oTranslator.m_bNativeData = psOptions->bNativeData;
2608 oTranslator.m_nLimit = psOptions->nLimit;
2609
2610 if( psOptions->nGroupTransactions )
2611 {
2612 if( !psOptions->nLayerTransaction )
2613 poODS->StartTransaction(psOptions->bForceTransaction);
2614 }
2615
2616 GIntBig nTotalEventsDone = 0;
2617
2618 /* -------------------------------------------------------------------- */
2619 /* Special case for -sql clause. No source layers required. */
2620 /* -------------------------------------------------------------------- */
2621 int nRetCode = 0;
2622
2623 if( psOptions->pszSQLStatement != nullptr )
2624 {
2625 /* Special case: if output=input, then we must likely destroy the */
2626 /* old table before to avoid transaction issues. */
2627 if( poDS == poODS && psOptions->pszNewLayerName != nullptr && bOverwrite )
2628 GetLayerAndOverwriteIfNecessary(poODS, psOptions->pszNewLayerName, bOverwrite, nullptr, nullptr, nullptr);
2629
2630 if( psOptions->pszWHERE != nullptr )
2631 CPLError( CE_Warning, CPLE_AppDefined, "-where clause ignored in combination with -sql." );
2632 if( CSLCount(psOptions->papszLayers) > 0 )
2633 CPLError( CE_Warning, CPLE_AppDefined, "layer names ignored in combination with -sql." );
2634
2635 OGRLayer *poResultSet =
2636 poDS->ExecuteSQL(
2637 psOptions->pszSQLStatement,
2638 (psOptions->pszGeomField == nullptr) ? reinterpret_cast<OGRGeometry*>(psOptions->hSpatialFilter) : nullptr,
2639 psOptions->pszDialect);
2640
2641 if( poResultSet != nullptr )
2642 {
2643 if( psOptions->hSpatialFilter != nullptr && psOptions->pszGeomField != nullptr )
2644 {
2645 int iGeomField = poResultSet->GetLayerDefn()->GetGeomFieldIndex(psOptions->pszGeomField);
2646 if( iGeomField >= 0 )
2647 poResultSet->SetSpatialFilter( iGeomField, reinterpret_cast<OGRGeometry*>(psOptions->hSpatialFilter) );
2648 else
2649 CPLError( CE_Warning, CPLE_AppDefined, "Cannot find geometry field %s.",
2650 psOptions->pszGeomField);
2651 }
2652
2653 GIntBig nCountLayerFeatures = 0;
2654 GDALProgressFunc pfnProgress = nullptr;
2655 void *pProgressArg = nullptr;
2656 if (psOptions->bDisplayProgress)
2657 {
2658 if (bRandomLayerReading)
2659 {
2660 pfnProgress = psOptions->pfnProgress;
2661 pProgressArg = psOptions->pProgressData;
2662 }
2663 else if (!poResultSet->TestCapability(OLCFastFeatureCount))
2664 {
2665 CPLError( CE_Warning, CPLE_AppDefined, "Progress turned off as fast feature count is not available.");
2666 psOptions->bDisplayProgress = false;
2667 }
2668 else
2669 {
2670 nCountLayerFeatures = poResultSet->GetFeatureCount();
2671 pfnProgress = psOptions->pfnProgress;
2672 pProgressArg = psOptions->pProgressData;
2673 }
2674 }
2675
2676 OGRLayer* poPassedLayer = poResultSet;
2677 if (psOptions->bSplitListFields)
2678 {
2679 auto poLayer = new OGRSplitListFieldLayer(poPassedLayer, psOptions->nMaxSplitListSubFields);
2680 poPassedLayer = poLayer;
2681 int nRet = poLayer->BuildLayerDefn(nullptr, nullptr);
2682 if (!nRet)
2683 {
2684 delete poPassedLayer;
2685 poPassedLayer = poResultSet;
2686 }
2687 }
2688
2689 /* -------------------------------------------------------------------- */
2690 /* Special case to improve user experience when translating into */
2691 /* single file shapefile and source has only one layer, and that */
2692 /* the layer name isn't specified */
2693 /* -------------------------------------------------------------------- */
2694 VSIStatBufL sStat;
2695 if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
2696 psOptions->pszNewLayerName == nullptr &&
2697 VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode) &&
2698 (EQUAL(CPLGetExtension(osDestFilename), "shp") ||
2699 EQUAL(CPLGetExtension(osDestFilename), "shz") ||
2700 EQUAL(CPLGetExtension(osDestFilename), "dbf")) )
2701 {
2702 psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
2703 }
2704
2705 auto psInfo = oSetup.Setup(poPassedLayer,
2706 psOptions->pszNewLayerName,
2707 psOptions,
2708 nTotalEventsDone);
2709
2710 poPassedLayer->ResetReading();
2711
2712 if( psInfo == nullptr ||
2713 !oTranslator.Translate( nullptr, psInfo.get(),
2714 nCountLayerFeatures, nullptr,
2715 nTotalEventsDone,
2716 pfnProgress, pProgressArg, psOptions ))
2717 {
2718 CPLError( CE_Failure, CPLE_AppDefined,
2719 "Terminating translation prematurely after failed\n"
2720 "translation from sql statement." );
2721
2722 nRetCode = 1;
2723 }
2724
2725 if (poPassedLayer != poResultSet)
2726 delete poPassedLayer;
2727
2728 poDS->ReleaseResultSet( poResultSet );
2729 }
2730 else
2731 {
2732 if( CPLGetLastErrorNo() != 0 )
2733 nRetCode = 1;
2734 }
2735 }
2736
2737 /* -------------------------------------------------------------------- */
2738 /* Special case for layer interleaving mode. */
2739 /* -------------------------------------------------------------------- */
2740 else if( bRandomLayerReading )
2741 {
2742 if (psOptions->bSplitListFields)
2743 {
2744 CPLError( CE_Failure, CPLE_AppDefined, "-splitlistfields not supported in this mode" );
2745 GDALVectorTranslateOptionsFree(psOptions);
2746 if( hDstDS == nullptr ) GDALClose( poODS );
2747 delete poGCPCoordTrans;
2748 return nullptr;
2749 }
2750
2751 // Make sure to probe all layers in case some are by default invisible
2752 for( char** papszIter = psOptions->papszLayers;
2753 papszIter && *papszIter; ++papszIter )
2754 {
2755 OGRLayer *poLayer = poDS->GetLayerByName(*papszIter);
2756
2757 if( poLayer == nullptr )
2758 {
2759 CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch requested layer %s!",
2760 *papszIter );
2761 GDALVectorTranslateOptionsFree(psOptions);
2762 if( hDstDS == nullptr ) GDALClose( poODS );
2763 delete poGCPCoordTrans;
2764 return nullptr;
2765 }
2766 }
2767
2768 const int nSrcLayerCount = poDS->GetLayerCount();
2769 std::vector<AssociatedLayers> pasAssocLayers(nSrcLayerCount);
2770
2771 /* -------------------------------------------------------------------- */
2772 /* Special case to improve user experience when translating into */
2773 /* single file shapefile and source has only one layer, and that */
2774 /* the layer name isn't specified */
2775 /* -------------------------------------------------------------------- */
2776 VSIStatBufL sStat;
2777 if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
2778 (CSLCount(psOptions->papszLayers) == 1 || nSrcLayerCount == 1) &&
2779 psOptions->pszNewLayerName == nullptr &&
2780 VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode) &&
2781 (EQUAL(CPLGetExtension(osDestFilename), "shp") ||
2782 EQUAL(CPLGetExtension(osDestFilename), "shz") ||
2783 EQUAL(CPLGetExtension(osDestFilename), "dbf")) )
2784 {
2785 psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
2786 }
2787
2788 GDALProgressFunc pfnProgress = nullptr;
2789 void *pProgressArg = nullptr;
2790 if ( !psOptions->bQuiet )
2791 {
2792 pfnProgress = psOptions->pfnProgress;
2793 pProgressArg = psOptions->pProgressData;
2794 }
2795
2796 /* -------------------------------------------------------------------- */
2797 /* If no target layer specified, use all source layers. */
2798 /* -------------------------------------------------------------------- */
2799 if ( CSLCount(psOptions->papszLayers) == 0)
2800 {
2801 psOptions->papszLayers = static_cast<char **>(
2802 CPLCalloc(sizeof(char*), nSrcLayerCount + 1));
2803 for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
2804 {
2805 OGRLayer *poLayer = poDS->GetLayer(iLayer);
2806
2807 if( poLayer == nullptr )
2808 {
2809 CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
2810 iLayer );
2811 GDALVectorTranslateOptionsFree(psOptions);
2812 if( hDstDS == nullptr ) GDALClose( poODS );
2813 delete poGCPCoordTrans;
2814 return nullptr;
2815 }
2816
2817 psOptions->papszLayers[iLayer] = CPLStrdup(poLayer->GetName());
2818 }
2819 }
2820 else
2821 {
2822 const bool bSrcIsOSM = (strcmp(poDS->GetDriverName(), "OSM") == 0);
2823 if ( bSrcIsOSM )
2824 {
2825 CPLString osInterestLayers = "SET interest_layers =";
2826 for( int iLayer = 0; psOptions->papszLayers[iLayer] != nullptr; iLayer++ )
2827 {
2828 if( iLayer != 0 ) osInterestLayers += ",";
2829 osInterestLayers += psOptions->papszLayers[iLayer];
2830 }
2831
2832 poDS->ExecuteSQL(osInterestLayers.c_str(), nullptr, nullptr);
2833 }
2834 }
2835
2836 /* -------------------------------------------------------------------- */
2837 /* First pass to set filters. */
2838 /* -------------------------------------------------------------------- */
2839 std::map<OGRLayer*, int> oMapLayerToIdx;
2840
2841 for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
2842 {
2843 OGRLayer *poLayer = poDS->GetLayer(iLayer);
2844 if( poLayer == nullptr )
2845 {
2846 CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
2847 iLayer );
2848 GDALVectorTranslateOptionsFree(psOptions);
2849 if( hDstDS == nullptr ) GDALClose( poODS );
2850 delete poGCPCoordTrans;
2851 return nullptr;
2852 }
2853
2854 pasAssocLayers[iLayer].poSrcLayer = poLayer;
2855
2856 if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) >= 0 )
2857 {
2858 if( psOptions->pszWHERE != nullptr )
2859 {
2860 if( poLayer->SetAttributeFilter( psOptions->pszWHERE ) != OGRERR_NONE )
2861 {
2862 CPLError( CE_Failure,
2863 CPLE_AppDefined,
2864 "SetAttributeFilter(%s) on layer '%s' failed.",
2865 psOptions->pszWHERE, poLayer->GetName() );
2866 if (!psOptions->bSkipFailures)
2867 {
2868 GDALVectorTranslateOptionsFree(psOptions);
2869 if( hDstDS == nullptr ) GDALClose( poODS );
2870 delete poGCPCoordTrans;
2871 return nullptr;
2872 }
2873 }
2874 }
2875
2876 ApplySpatialFilter(poLayer,
2877 reinterpret_cast<OGRGeometry*>(psOptions->hSpatialFilter),
2878 poSpatSRS, psOptions->pszGeomField,
2879 poSourceSRS );
2880
2881 oMapLayerToIdx[ poLayer ] = iLayer;
2882 }
2883 }
2884
2885 /* -------------------------------------------------------------------- */
2886 /* Second pass to process features in a interleaved layer mode. */
2887 /* -------------------------------------------------------------------- */
2888 bool bTargetLayersHaveBeenCreated = false;
2889 while( true )
2890 {
2891 OGRLayer* poFeatureLayer = nullptr;
2892 OGRFeature* poFeature = poDS->GetNextFeature(&poFeatureLayer,
2893 nullptr,
2894 pfnProgress,
2895 pProgressArg);
2896 if( poFeature == nullptr )
2897 break;
2898 std::map<OGRLayer*, int>::const_iterator oIter =
2899 oMapLayerToIdx.find(poFeatureLayer);
2900 if( oIter == oMapLayerToIdx.end() )
2901 {
2902 // Feature in a layer that is not a layer of interest.
2903 OGRFeature::DestroyFeature(poFeature);
2904 }
2905 else
2906 {
2907 if( !bTargetLayersHaveBeenCreated )
2908 {
2909 // We defer target layer creation at the first feature
2910 // retrieved since getting the layer definition can be
2911 // costly (case of the GMLAS driver) and thus we'd better
2912 // taking advantage from the progress callback of
2913 // GetNextFeature.
2914 bTargetLayersHaveBeenCreated = true;
2915 for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
2916 {
2917 OGRLayer *poLayer = poDS->GetLayer(iLayer);
2918 if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) < 0 )
2919 continue;
2920
2921 auto psInfo = oSetup.Setup(poLayer,
2922 psOptions->pszNewLayerName,
2923 psOptions,
2924 nTotalEventsDone);
2925
2926 if( psInfo == nullptr && !psOptions->bSkipFailures )
2927 {
2928 GDALVectorTranslateOptionsFree(psOptions);
2929 if( hDstDS == nullptr ) GDALClose( poODS );
2930 delete poGCPCoordTrans;
2931 OGRFeature::DestroyFeature(poFeature);
2932 return nullptr;
2933 }
2934
2935 pasAssocLayers[iLayer].psInfo = std::move(psInfo);
2936 }
2937 if( nRetCode )
2938 break;
2939 }
2940
2941 int iLayer = oIter->second;
2942 TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo.get();
2943 if( (psInfo == nullptr ||
2944 !oTranslator.Translate( poFeature, psInfo,
2945 0, nullptr,
2946 nTotalEventsDone,
2947 nullptr, nullptr, psOptions ))
2948 && !psOptions->bSkipFailures )
2949 {
2950 CPLError( CE_Failure, CPLE_AppDefined,
2951 "Terminating translation prematurely after failed\n"
2952 "translation of layer %s (use -skipfailures to skip errors)",
2953 poFeatureLayer->GetName() );
2954
2955 nRetCode = 1;
2956 break;
2957 }
2958 if( psInfo == nullptr )
2959 OGRFeature::DestroyFeature(poFeature);
2960 }
2961 } // while true
2962
2963 if (pfnProgress)
2964 {
2965 pfnProgress(1.0, "", pProgressArg);
2966 }
2967
2968 if( !bTargetLayersHaveBeenCreated )
2969 {
2970 // bTargetLayersHaveBeenCreated not used after here.
2971 // bTargetLayersHaveBeenCreated = true;
2972 for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
2973 {
2974 OGRLayer *poLayer = poDS->GetLayer(iLayer);
2975 if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) < 0 )
2976 continue;
2977
2978 auto psInfo = oSetup.Setup(poLayer,
2979 psOptions->pszNewLayerName,
2980 psOptions,
2981 nTotalEventsDone);
2982
2983 if( psInfo == nullptr && !psOptions->bSkipFailures )
2984 {
2985 GDALVectorTranslateOptionsFree(psOptions);
2986 if( hDstDS == nullptr ) GDALClose( poODS );
2987 delete poGCPCoordTrans;
2988 return nullptr;
2989 }
2990
2991 pasAssocLayers[iLayer].psInfo = std::move(psInfo);
2992 }
2993 }
2994 }
2995
2996 else
2997 {
2998 int nLayerCount = 0;
2999 std::vector<OGRLayer*> apoLayers;
3000
3001 /* -------------------------------------------------------------------- */
3002 /* Process each data source layer. */
3003 /* -------------------------------------------------------------------- */
3004 if ( CSLCount(psOptions->papszLayers) == 0)
3005 {
3006 nLayerCount = poDS->GetLayerCount();
3007 apoLayers.resize(nLayerCount);
3008
3009 for( int iLayer = 0;
3010 iLayer < nLayerCount;
3011 iLayer++ )
3012 {
3013 OGRLayer *poLayer = poDS->GetLayer(iLayer);
3014
3015 if( poLayer == nullptr )
3016 {
3017 CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch advertised layer %d!",
3018 iLayer );
3019 GDALVectorTranslateOptionsFree(psOptions);
3020 if( hDstDS == nullptr ) GDALClose( poODS );
3021 delete poGCPCoordTrans;
3022 return nullptr;
3023 }
3024
3025 apoLayers[iLayer] = poLayer;
3026 }
3027 }
3028 /* -------------------------------------------------------------------- */
3029 /* Process specified data source layers. */
3030 /* -------------------------------------------------------------------- */
3031 else
3032 {
3033 nLayerCount = CSLCount(psOptions->papszLayers);
3034 apoLayers.resize(nLayerCount);
3035
3036 for( int iLayer = 0;
3037 psOptions->papszLayers[iLayer] != nullptr;
3038 iLayer++ )
3039 {
3040 OGRLayer *poLayer = poDS->GetLayerByName(psOptions->papszLayers[iLayer]);
3041
3042 if( poLayer == nullptr )
3043 {
3044 CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch requested layer '%s'!",
3045 psOptions->papszLayers[iLayer] );
3046 if (!psOptions->bSkipFailures)
3047 {
3048 GDALVectorTranslateOptionsFree(psOptions);
3049 if( hDstDS == nullptr ) GDALClose( poODS );
3050 delete poGCPCoordTrans;
3051 return nullptr;
3052 }
3053 }
3054
3055 apoLayers[iLayer] = poLayer;
3056 }
3057 }
3058
3059 /* -------------------------------------------------------------------- */
3060 /* Special case to improve user experience when translating into */
3061 /* single file shapefile and source has only one layer, and that */
3062 /* the layer name isn't specified */
3063 /* -------------------------------------------------------------------- */
3064 VSIStatBufL sStat;
3065 if (EQUAL(poDriver->GetDescription(), "ESRI Shapefile") &&
3066 nLayerCount == 1 && psOptions->pszNewLayerName == nullptr &&
3067 VSIStatL(osDestFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode) &&
3068 (EQUAL(CPLGetExtension(osDestFilename), "shp") ||
3069 EQUAL(CPLGetExtension(osDestFilename), "shz") ||
3070 EQUAL(CPLGetExtension(osDestFilename), "dbf")) )
3071 {
3072 psOptions->pszNewLayerName = CPLStrdup(CPLGetBasename(osDestFilename));
3073 }
3074
3075 std::vector<GIntBig> anLayerCountFeatures;
3076 anLayerCountFeatures.resize(nLayerCount);
3077 GIntBig nCountLayersFeatures = 0;
3078 GIntBig nAccCountFeatures = 0;
3079
3080 /* First pass to apply filters and count all features if necessary */
3081 for( int iLayer = 0; iLayer < nLayerCount; iLayer++ )
3082 {
3083 OGRLayer *poLayer = apoLayers[iLayer];
3084 if (poLayer == nullptr)
3085 continue;
3086
3087 if( psOptions->pszWHERE != nullptr )
3088 {
3089 if( poLayer->SetAttributeFilter( psOptions->pszWHERE ) != OGRERR_NONE )
3090 {
3091 CPLError( CE_Failure, CPLE_AppDefined, "SetAttributeFilter(%s) on layer '%s' failed.",
3092 psOptions->pszWHERE, poLayer->GetName() );
3093 if (!psOptions->bSkipFailures)
3094 {
3095 GDALVectorTranslateOptionsFree(psOptions);
3096 if( hDstDS == nullptr ) GDALClose( poODS );
3097 delete poGCPCoordTrans;
3098 return nullptr;
3099 }
3100 }
3101 }
3102
3103 ApplySpatialFilter(poLayer, reinterpret_cast<OGRGeometry*>(psOptions->hSpatialFilter), poSpatSRS, psOptions->pszGeomField, poSourceSRS);
3104
3105 if (psOptions->bDisplayProgress)
3106 {
3107 if (!poLayer->TestCapability(OLCFastFeatureCount))
3108 {
3109 CPLError(CE_Warning, CPLE_NotSupported, "Progress turned off as fast feature count is not available.");
3110 psOptions->bDisplayProgress = false;
3111 }
3112 else
3113 {
3114 anLayerCountFeatures[iLayer] = poLayer->GetFeatureCount();
3115 nCountLayersFeatures += anLayerCountFeatures[iLayer];
3116 }
3117 }
3118 }
3119
3120 /* Second pass to do the real job */
3121 for( int iLayer = 0; iLayer < nLayerCount && nRetCode == 0; iLayer++ )
3122 {
3123 OGRLayer *poLayer = apoLayers[iLayer];
3124 if (poLayer == nullptr)
3125 continue;
3126
3127 GDALProgressFunc pfnProgress = nullptr;
3128 void *pProgressArg = nullptr;
3129
3130 OGRLayer* poPassedLayer = poLayer;
3131 if (psOptions->bSplitListFields)
3132 {
3133 auto poSLFLayer = new OGRSplitListFieldLayer(poPassedLayer, psOptions->nMaxSplitListSubFields);
3134 poPassedLayer = poSLFLayer;
3135
3136 if (psOptions->bDisplayProgress && psOptions->nMaxSplitListSubFields != 1 &&
3137 nCountLayersFeatures != 0)
3138 {
3139 pfnProgress = GDALScaledProgress;
3140 pProgressArg =
3141 GDALCreateScaledProgress(nAccCountFeatures * 1.0 / nCountLayersFeatures,
3142 (nAccCountFeatures + anLayerCountFeatures[iLayer] / 2) * 1.0 / nCountLayersFeatures,
3143 psOptions->pfnProgress,
3144 psOptions->pProgressData);
3145 }
3146 else
3147 {
3148 pfnProgress = nullptr;
3149 pProgressArg = nullptr;
3150 }
3151
3152 int nRet = poSLFLayer->BuildLayerDefn(pfnProgress, pProgressArg);
3153 if (!nRet)
3154 {
3155 delete poPassedLayer;
3156 poPassedLayer = poLayer;
3157 }
3158
3159 if (psOptions->bDisplayProgress)
3160 GDALDestroyScaledProgress(pProgressArg);
3161 pfnProgress = nullptr;
3162 pProgressArg = nullptr;
3163 }
3164
3165 if (psOptions->bDisplayProgress)
3166 {
3167 if( nCountLayersFeatures != 0 )
3168 {
3169 pfnProgress = GDALScaledProgress;
3170 GIntBig nStart = 0;
3171 if (poPassedLayer != poLayer && psOptions->nMaxSplitListSubFields != 1)
3172 nStart = anLayerCountFeatures[iLayer] / 2;
3173 pProgressArg =
3174 GDALCreateScaledProgress((nAccCountFeatures + nStart) * 1.0 / nCountLayersFeatures,
3175 (nAccCountFeatures + anLayerCountFeatures[iLayer]) * 1.0 / nCountLayersFeatures,
3176 psOptions->pfnProgress,
3177 psOptions->pProgressData);
3178 }
3179 }
3180
3181 nAccCountFeatures += anLayerCountFeatures[iLayer];
3182
3183 auto psInfo = oSetup.Setup(poPassedLayer,
3184 psOptions->pszNewLayerName,
3185 psOptions,
3186 nTotalEventsDone);
3187
3188 poPassedLayer->ResetReading();
3189
3190 if( (psInfo == nullptr ||
3191 !oTranslator.Translate( nullptr, psInfo.get(),
3192 anLayerCountFeatures[iLayer], nullptr,
3193 nTotalEventsDone,
3194 pfnProgress, pProgressArg, psOptions ))
3195 && !psOptions->bSkipFailures )
3196 {
3197 CPLError( CE_Failure, CPLE_AppDefined,
3198 "Terminating translation prematurely after failed\n"
3199 "translation of layer %s (use -skipfailures to skip errors)",
3200 poLayer->GetName() );
3201
3202 nRetCode = 1;
3203 }
3204
3205 if (poPassedLayer != poLayer)
3206 delete poPassedLayer;
3207
3208 if (psOptions->bDisplayProgress)
3209 GDALDestroyScaledProgress(pProgressArg);
3210 }
3211 }
3212 /* -------------------------------------------------------------------- */
3213 /* Process DS style table */
3214 /* -------------------------------------------------------------------- */
3215
3216 poODS->SetStyleTable( poDS->GetStyleTable () );
3217
3218 if( psOptions->nGroupTransactions )
3219 {
3220 if( !psOptions->nLayerTransaction )
3221 {
3222 if( nRetCode != 0 && !psOptions->bSkipFailures )
3223 poODS->RollbackTransaction();
3224 else
3225 poODS->CommitTransaction();
3226 }
3227 }
3228
3229 delete poGCPCoordTrans;
3230
3231 GDALVectorTranslateOptionsFree(psOptions);
3232 if(nRetCode == 0)
3233 return static_cast<GDALDatasetH>(poODS);
3234
3235 if( hDstDS == nullptr ) GDALClose( poODS );
3236 return nullptr;
3237 }
3238
3239 /************************************************************************/
3240 /* SetZ() */
3241 /************************************************************************/
3242
3243 namespace {
3244 class SetZVisitor: public OGRDefaultGeometryVisitor
3245 {
3246 double m_dfZ;
3247
3248 public:
SetZVisitor(double dfZ)3249 explicit SetZVisitor(double dfZ): m_dfZ(dfZ) {}
3250
3251 using OGRDefaultGeometryVisitor::visit;
3252
visit(OGRPoint * poPoint)3253 void visit(OGRPoint* poPoint) override
3254 {
3255 poPoint->setZ(m_dfZ);
3256 }
3257 };
3258 }
3259
SetZ(OGRGeometry * poGeom,double dfZ)3260 static void SetZ (OGRGeometry* poGeom, double dfZ )
3261 {
3262 if (poGeom == nullptr)
3263 return;
3264 SetZVisitor visitor(dfZ);
3265 poGeom->set3D(true);
3266 poGeom->accept(&visitor);
3267 }
3268
3269 /************************************************************************/
3270 /* ForceCoordDimension() */
3271 /************************************************************************/
3272
ForceCoordDimension(int eGType,int nCoordDim)3273 static int ForceCoordDimension(int eGType, int nCoordDim)
3274 {
3275 if( nCoordDim == 2 && eGType != wkbNone )
3276 return wkbFlatten(eGType);
3277 else if( nCoordDim == 3 && eGType != wkbNone )
3278 return wkbSetZ(wkbFlatten(eGType));
3279 else if( nCoordDim == COORD_DIM_XYM && eGType != wkbNone )
3280 return wkbSetM(wkbFlatten(eGType));
3281 else if( nCoordDim == 4 && eGType != wkbNone )
3282 return OGR_GT_SetModifier(static_cast<OGRwkbGeometryType>(eGType), TRUE, TRUE);
3283 else
3284 return eGType;
3285 }
3286
3287 /************************************************************************/
3288 /* GetLayerAndOverwriteIfNecessary() */
3289 /************************************************************************/
3290
GetLayerAndOverwriteIfNecessary(GDALDataset * poDstDS,const char * pszNewLayerName,bool bOverwrite,bool * pbErrorOccurred,bool * pbOverwriteActuallyDone,bool * pbAddOverwriteLCO)3291 static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
3292 const char* pszNewLayerName,
3293 bool bOverwrite,
3294 bool* pbErrorOccurred,
3295 bool* pbOverwriteActuallyDone,
3296 bool* pbAddOverwriteLCO)
3297 {
3298 if( pbErrorOccurred )
3299 *pbErrorOccurred = false;
3300 if( pbOverwriteActuallyDone )
3301 *pbOverwriteActuallyDone = false;
3302 if( pbAddOverwriteLCO )
3303 *pbAddOverwriteLCO = false;
3304
3305 /* GetLayerByName() can instantiate layers that would have been */
3306 /* 'hidden' otherwise, for example, non-spatial tables in a */
3307 /* PostGIS-enabled database, so this apparently useless command is */
3308 /* not useless. (#4012) */
3309 CPLPushErrorHandler(CPLQuietErrorHandler);
3310 OGRLayer* poDstLayer = poDstDS->GetLayerByName(pszNewLayerName);
3311 CPLPopErrorHandler();
3312 CPLErrorReset();
3313
3314 int iLayer = -1;
3315 if (poDstLayer != nullptr)
3316 {
3317 const int nLayerCount = poDstDS->GetLayerCount();
3318 for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
3319 {
3320 OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
3321 if (poLayer == poDstLayer)
3322 break;
3323 }
3324
3325 if (iLayer == nLayerCount)
3326 /* should not happen with an ideal driver */
3327 poDstLayer = nullptr;
3328 }
3329
3330 /* -------------------------------------------------------------------- */
3331 /* If the user requested overwrite, and we have the layer in */
3332 /* question we need to delete it now so it will get recreated */
3333 /* (overwritten). */
3334 /* -------------------------------------------------------------------- */
3335 if( poDstLayer != nullptr && bOverwrite )
3336 {
3337 /* When using the CARTO driver we don't want to delete the layer if */
3338 /* it's going to be recreated. Instead we mark it to be overwritten */
3339 /* when the new creation is requested */
3340 if ( poDstDS->GetDriver()->GetMetadataItem(
3341 GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3342 strstr(poDstDS->GetDriver()->GetMetadataItem(
3343 GDAL_DS_LAYER_CREATIONOPTIONLIST), "CARTODBFY") != nullptr )
3344 {
3345 if ( pbAddOverwriteLCO )
3346 *pbAddOverwriteLCO = true;
3347 if( pbOverwriteActuallyDone )
3348 *pbOverwriteActuallyDone = true;
3349
3350 } else if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
3351 {
3352 CPLError( CE_Failure, CPLE_AppDefined,
3353 "DeleteLayer() failed when overwrite requested." );
3354 if( pbErrorOccurred )
3355 *pbErrorOccurred = true;
3356 }
3357 else
3358 {
3359 if( pbOverwriteActuallyDone )
3360 *pbOverwriteActuallyDone = true;
3361 }
3362 poDstLayer = nullptr;
3363 }
3364
3365 return poDstLayer;
3366 }
3367
3368 /************************************************************************/
3369 /* ConvertType() */
3370 /************************************************************************/
3371
ConvertType(GeomTypeConversion eGeomTypeConversion,OGRwkbGeometryType eGType)3372 static OGRwkbGeometryType ConvertType(GeomTypeConversion eGeomTypeConversion,
3373 OGRwkbGeometryType eGType)
3374 {
3375 OGRwkbGeometryType eRetType = eGType;
3376
3377 if ( eGeomTypeConversion == GTC_CONVERT_TO_LINEAR ||
3378 eGeomTypeConversion == GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR )
3379 {
3380 eRetType = OGR_GT_GetLinear(eRetType);
3381 }
3382
3383 if ( eGeomTypeConversion == GTC_PROMOTE_TO_MULTI ||
3384 eGeomTypeConversion == GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR )
3385 {
3386 if( eRetType == wkbTriangle || eRetType == wkbTIN ||
3387 eRetType == wkbPolyhedralSurface )
3388 {
3389 eRetType = wkbMultiPolygon;
3390 }
3391 else if( !OGR_GT_IsSubClassOf(eRetType, wkbGeometryCollection) )
3392 {
3393 eRetType = OGR_GT_GetCollection(eRetType);
3394 }
3395 }
3396
3397 if ( eGeomTypeConversion == GTC_CONVERT_TO_CURVE )
3398 eRetType = OGR_GT_GetCurve(eRetType);
3399
3400 return eRetType;
3401 }
3402
3403 /************************************************************************/
3404 /* DoFieldTypeConversion() */
3405 /************************************************************************/
3406
3407 static
DoFieldTypeConversion(GDALDataset * poDstDS,OGRFieldDefn & oFieldDefn,char ** papszFieldTypesToString,char ** papszMapFieldType,bool bUnsetFieldWidth,bool bQuiet,bool bForceNullable,bool bUnsetDefault)3408 void DoFieldTypeConversion(GDALDataset* poDstDS, OGRFieldDefn& oFieldDefn,
3409 char** papszFieldTypesToString,
3410 char** papszMapFieldType,
3411 bool bUnsetFieldWidth,
3412 bool bQuiet,
3413 bool bForceNullable,
3414 bool bUnsetDefault)
3415 {
3416 if (papszFieldTypesToString != nullptr )
3417 {
3418 CPLString osLookupString;
3419 osLookupString.Printf("%s(%s)",
3420 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
3421 OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
3422
3423 int iIdx = CSLFindString(papszFieldTypesToString, osLookupString);
3424 if( iIdx < 0 )
3425 iIdx = CSLFindString(papszFieldTypesToString,
3426 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
3427 if( iIdx < 0 )
3428 iIdx = CSLFindString(papszFieldTypesToString, "All");
3429 if( iIdx >= 0 )
3430 {
3431 oFieldDefn.SetSubType(OFSTNone);
3432 oFieldDefn.SetType(OFTString);
3433 }
3434 }
3435 else if (papszMapFieldType != nullptr)
3436 {
3437 CPLString osLookupString;
3438 osLookupString.Printf("%s(%s)",
3439 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
3440 OGRFieldDefn::GetFieldSubTypeName(oFieldDefn.GetSubType()));
3441
3442 const char* pszType = CSLFetchNameValue(papszMapFieldType, osLookupString);
3443 if( pszType == nullptr )
3444 pszType = CSLFetchNameValue(papszMapFieldType,
3445 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()));
3446 if( pszType == nullptr )
3447 pszType = CSLFetchNameValue(papszMapFieldType, "All");
3448 if( pszType != nullptr )
3449 {
3450 int iSubType;
3451 int iType = GetFieldType(pszType, &iSubType);
3452 if( iType >= 0 && iSubType >= 0 )
3453 {
3454 oFieldDefn.SetSubType(OFSTNone);
3455 oFieldDefn.SetType(static_cast<OGRFieldType>(iType));
3456 oFieldDefn.SetSubType(static_cast<OGRFieldSubType>(iSubType));
3457 if( iType == OFTInteger )
3458 oFieldDefn.SetWidth(0);
3459 }
3460 }
3461 }
3462 if( bUnsetFieldWidth )
3463 {
3464 oFieldDefn.SetWidth(0);
3465 oFieldDefn.SetPrecision(0);
3466 }
3467 if( bForceNullable )
3468 oFieldDefn.SetNullable(TRUE);
3469 if( bUnsetDefault )
3470 oFieldDefn.SetDefault(nullptr);
3471
3472 if( poDstDS->GetDriver() != nullptr &&
3473 poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) != nullptr &&
3474 strstr(poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES),
3475 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType())) == nullptr )
3476 {
3477 if( oFieldDefn.GetType() == OFTInteger64 )
3478 {
3479 if( !bQuiet )
3480 {
3481 CPLError(CE_Warning, CPLE_AppDefined,
3482 "The output driver does not seem to natively support %s "
3483 "type for field %s. Converting it to Real instead. "
3484 "-mapFieldType can be used to control field type conversion.",
3485 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
3486 oFieldDefn.GetNameRef());
3487 }
3488 oFieldDefn.SetType(OFTReal);
3489 }
3490 else if( !bQuiet )
3491 {
3492 CPLError(CE_Warning, CPLE_AppDefined,
3493 "The output driver does not natively support %s type for "
3494 "field %s. Misconversion can happen. "
3495 "-mapFieldType can be used to control field type conversion.",
3496 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
3497 oFieldDefn.GetNameRef());
3498 }
3499 }
3500 else if( poDstDS->GetDriver() != nullptr &&
3501 poDstDS->GetDriver()->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) == nullptr )
3502 {
3503 // All drivers supporting OFTInteger64 should advertise it theoretically
3504 if( oFieldDefn.GetType() == OFTInteger64 )
3505 {
3506 if( !bQuiet )
3507 {
3508 CPLError(CE_Warning, CPLE_AppDefined,
3509 "The output driver does not seem to natively support %s type "
3510 "for field %s. Converting it to Real instead. "
3511 "-mapFieldType can be used to control field type conversion.",
3512 OGRFieldDefn::GetFieldTypeName(oFieldDefn.GetType()),
3513 oFieldDefn.GetNameRef());
3514 }
3515 oFieldDefn.SetType(OFTReal);
3516 }
3517 }
3518 }
3519
3520 /************************************************************************/
3521 /* SetupTargetLayer::Setup() */
3522 /************************************************************************/
3523
Setup(OGRLayer * poSrcLayer,const char * pszNewLayerName,GDALVectorTranslateOptions * psOptions,GIntBig & nTotalEventsDone)3524 std::unique_ptr<TargetLayerInfo> SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
3525 const char* pszNewLayerName,
3526 GDALVectorTranslateOptions *psOptions,
3527 GIntBig& nTotalEventsDone)
3528 {
3529 int eGType = m_eGType;
3530 bool bPreserveFID = m_bPreserveFID;
3531 bool bAppend = m_bAppend;
3532
3533 if( pszNewLayerName == nullptr )
3534 pszNewLayerName = poSrcLayer->GetName();
3535
3536 /* -------------------------------------------------------------------- */
3537 /* Get other info. */
3538 /* -------------------------------------------------------------------- */
3539 OGRFeatureDefn *poSrcFDefn = poSrcLayer->GetLayerDefn();
3540
3541 /* -------------------------------------------------------------------- */
3542 /* Find requested geometry fields. */
3543 /* -------------------------------------------------------------------- */
3544 std::vector<int> anRequestedGeomFields;
3545 const int nSrcGeomFieldCount = poSrcFDefn->GetGeomFieldCount();
3546 if (m_papszSelFields && !bAppend )
3547 {
3548 for( int iField=0; m_papszSelFields[iField] != nullptr; iField++)
3549 {
3550 int iSrcField = poSrcFDefn->GetFieldIndex(m_papszSelFields[iField]);
3551 if (iSrcField >= 0)
3552 {
3553 /* do nothing */
3554 }
3555 else
3556 {
3557 iSrcField = poSrcFDefn->GetGeomFieldIndex(m_papszSelFields[iField]);
3558 if( iSrcField >= 0)
3559 {
3560 anRequestedGeomFields.push_back(iSrcField);
3561 }
3562 else
3563 {
3564 CPLError( CE_Failure, CPLE_AppDefined, "Field '%s' not found in source layer.",
3565 m_papszSelFields[iField] );
3566 if( !psOptions->bSkipFailures )
3567 return nullptr;
3568 }
3569 }
3570 }
3571
3572 if( anRequestedGeomFields.size() > 1 &&
3573 !m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
3574 {
3575 CPLError( CE_Failure, CPLE_AppDefined, "Several geometry fields requested, but output "
3576 "datasource does not support multiple geometry "
3577 "fields." );
3578 if( !psOptions->bSkipFailures )
3579 return nullptr;
3580 else
3581 anRequestedGeomFields.resize(0);
3582 }
3583 }
3584
3585 OGRSpatialReference* poOutputSRS = m_poOutputSRS;
3586 if( poOutputSRS == nullptr && !m_bNullifyOutputSRS )
3587 {
3588 if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.empty() )
3589 poOutputSRS = poSrcLayer->GetSpatialRef();
3590 else if( anRequestedGeomFields.size() == 1 )
3591 {
3592 int iSrcGeomField = anRequestedGeomFields[0];
3593 poOutputSRS = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->
3594 GetSpatialRef();
3595 }
3596 }
3597
3598 int iSrcZField = -1;
3599 if (m_pszZField != nullptr)
3600 {
3601 iSrcZField = poSrcFDefn->GetFieldIndex(m_pszZField);
3602 if( iSrcZField < 0 )
3603 {
3604 CPLError(CE_Warning, CPLE_AppDefined,
3605 "zfield '%s' does not exist in layer %s",
3606 m_pszZField, poSrcLayer->GetName());
3607 }
3608 }
3609
3610 /* -------------------------------------------------------------------- */
3611 /* Find the layer. */
3612 /* -------------------------------------------------------------------- */
3613
3614 bool bErrorOccurred;
3615 bool bOverwriteActuallyDone;
3616 bool bAddOverwriteLCO;
3617 OGRLayer *poDstLayer =
3618 GetLayerAndOverwriteIfNecessary(m_poDstDS,
3619 pszNewLayerName,
3620 m_bOverwrite,
3621 &bErrorOccurred,
3622 &bOverwriteActuallyDone,
3623 &bAddOverwriteLCO);
3624 if( bErrorOccurred )
3625 return nullptr;
3626
3627 /* -------------------------------------------------------------------- */
3628 /* If the layer does not exist, then create it. */
3629 /* -------------------------------------------------------------------- */
3630 if( poDstLayer == nullptr )
3631 {
3632 if( !m_poDstDS->TestCapability( ODsCCreateLayer ) )
3633 {
3634 CPLError( CE_Failure, CPLE_AppDefined,
3635 "Layer '%s' does not already exist in the output dataset, and "
3636 "cannot be created by the output driver.",
3637 pszNewLayerName );
3638 return nullptr;
3639 }
3640
3641 bool bForceGType = ( eGType != GEOMTYPE_UNCHANGED );
3642 if( !bForceGType )
3643 {
3644 if( anRequestedGeomFields.empty() )
3645 {
3646 eGType = poSrcFDefn->GetGeomType();
3647 }
3648 else if( anRequestedGeomFields.size() == 1 )
3649 {
3650 int iSrcGeomField = anRequestedGeomFields[0];
3651 eGType = poSrcFDefn->GetGeomFieldDefn(iSrcGeomField)->GetType();
3652 }
3653 else
3654 {
3655 eGType = wkbNone;
3656 }
3657
3658 bool bHasZ = CPL_TO_BOOL(wkbHasZ(static_cast<OGRwkbGeometryType>(eGType)));
3659 eGType = ConvertType(m_eGeomTypeConversion, static_cast<OGRwkbGeometryType>(eGType));
3660
3661 if ( m_bExplodeCollections )
3662 {
3663 const OGRwkbGeometryType eFGType = wkbFlatten(eGType);
3664 if (eFGType == wkbMultiPoint)
3665 {
3666 eGType = wkbPoint;
3667 }
3668 else if (eFGType == wkbMultiLineString)
3669 {
3670 eGType = wkbLineString;
3671 }
3672 else if (eFGType == wkbMultiPolygon)
3673 {
3674 eGType = wkbPolygon;
3675 }
3676 else if (eFGType == wkbGeometryCollection ||
3677 eFGType == wkbMultiCurve ||
3678 eFGType == wkbMultiSurface)
3679 {
3680 eGType = wkbUnknown;
3681 }
3682 }
3683
3684 if ( bHasZ || (iSrcZField >= 0 && eGType != wkbNone) )
3685 eGType = wkbSetZ(static_cast<OGRwkbGeometryType>(eGType));
3686 }
3687
3688 eGType = ForceCoordDimension(eGType, m_nCoordDim);
3689
3690 CPLErrorReset();
3691
3692 char** papszLCOTemp = CSLDuplicate(m_papszLCO);
3693
3694 int eGCreateLayerType = eGType;
3695 if( anRequestedGeomFields.empty() &&
3696 nSrcGeomFieldCount > 1 &&
3697 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
3698 {
3699 eGCreateLayerType = wkbNone;
3700 }
3701 // If the source layer has a single geometry column that is not nullable
3702 // and that ODsCCreateGeomFieldAfterCreateLayer is available, use it
3703 // so as to be able to set the not null constraint (if the driver supports it)
3704 // Same if the source geometry column has a non empty name that is not
3705 // overridden
3706 else if( eGType != wkbNone &&
3707 anRequestedGeomFields.empty() &&
3708 nSrcGeomFieldCount == 1 &&
3709 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
3710 ((!poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
3711 CSLFetchNameValue(m_papszLCO, "GEOMETRY_NULLABLE") == nullptr &&
3712 !m_bForceNullable) ||
3713 (poSrcLayer->GetGeometryColumn() != nullptr &&
3714 CSLFetchNameValue(m_papszLCO, "GEOMETRY_NAME") == nullptr &&
3715 !EQUAL(poSrcLayer->GetGeometryColumn(), "") &&
3716 poSrcFDefn->GetFieldIndex(poSrcLayer->GetGeometryColumn()) < 0)) )
3717 {
3718 anRequestedGeomFields.push_back(0);
3719 eGCreateLayerType = wkbNone;
3720 }
3721 else if( anRequestedGeomFields.size() == 1 &&
3722 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
3723 {
3724 eGCreateLayerType = wkbNone;
3725 }
3726
3727 // If the source feature first geometry column is not nullable
3728 // and that GEOMETRY_NULLABLE creation option is available, use it
3729 // so as to be able to set the not null constraint (if the driver supports it)
3730 if( eGType != wkbNone &&
3731 anRequestedGeomFields.empty() &&
3732 nSrcGeomFieldCount >= 1 &&
3733 !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
3734 m_poDstDS->GetDriver()->GetMetadataItem(
3735 GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3736 strstr(m_poDstDS->GetDriver()->GetMetadataItem(
3737 GDAL_DS_LAYER_CREATIONOPTIONLIST), "GEOMETRY_NULLABLE") != nullptr &&
3738 CSLFetchNameValue(m_papszLCO, "GEOMETRY_NULLABLE") == nullptr &&
3739 !m_bForceNullable )
3740 {
3741 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "GEOMETRY_NULLABLE", "NO");
3742 CPLDebug("GDALVectorTranslate", "Using GEOMETRY_NULLABLE=NO");
3743 }
3744
3745 // Use source geometry field name as much as possible
3746 if( eGType != wkbNone &&
3747 m_poDstDS->GetDriver()->GetMetadataItem(
3748 GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3749 strstr(m_poDstDS->GetDriver()->GetMetadataItem(
3750 GDAL_DS_LAYER_CREATIONOPTIONLIST), "GEOMETRY_NAME") != nullptr &&
3751 CSLFetchNameValue(m_papszLCO, "GEOMETRY_NAME") == nullptr )
3752 {
3753 int iSrcGeomField = -1;
3754 if( anRequestedGeomFields.empty() &&
3755 (nSrcGeomFieldCount == 1 ||
3756 (!m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
3757 nSrcGeomFieldCount > 1) ) )
3758 {
3759 iSrcGeomField = 0;
3760 }
3761 else if( anRequestedGeomFields.size() == 1 )
3762 {
3763 iSrcGeomField = anRequestedGeomFields[0];
3764 }
3765
3766 if( iSrcGeomField >= 0 )
3767 {
3768 const char* pszGFldName = poSrcFDefn->GetGeomFieldDefn(
3769 iSrcGeomField)->GetNameRef();
3770 if( pszGFldName != nullptr && !EQUAL(pszGFldName, "") &&
3771 poSrcFDefn->GetFieldIndex(pszGFldName) < 0 )
3772 {
3773 papszLCOTemp = CSLSetNameValue(papszLCOTemp,
3774 "GEOMETRY_NAME", pszGFldName);
3775 }
3776 }
3777 }
3778
3779 // Force FID column as 64 bit if the source feature has a 64 bit FID,
3780 // the target driver supports 64 bit FID and the user didn't set it
3781 // manually.
3782 if( poSrcLayer->GetMetadataItem(OLMD_FID64) != nullptr &&
3783 EQUAL(poSrcLayer->GetMetadataItem(OLMD_FID64), "YES") &&
3784 m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3785 strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "FID64") != nullptr &&
3786 CSLFetchNameValue(m_papszLCO, "FID64") == nullptr )
3787 {
3788 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID64", "YES");
3789 CPLDebug("GDALVectorTranslate", "Using FID64=YES");
3790 }
3791
3792 // If output driver supports FID layer creation option, set it with
3793 // the FID column name of the source layer
3794 if( !m_bUnsetFid && !bAppend &&
3795 poSrcLayer->GetFIDColumn() != nullptr &&
3796 !EQUAL(poSrcLayer->GetFIDColumn(), "") &&
3797 m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3798 strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "='FID'") != nullptr &&
3799 CSLFetchNameValue(m_papszLCO, "FID") == nullptr )
3800 {
3801 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "FID", poSrcLayer->GetFIDColumn());
3802 CPLDebug("GDALVectorTranslate", "Using FID=%s and -preserve_fid", poSrcLayer->GetFIDColumn());
3803 bPreserveFID = true;
3804 }
3805
3806 // If bAddOverwriteLCO is ON (set up when overwriting a CARTO layer),
3807 // set OVERWRITE to YES so the new layer overwrites the old one
3808 if (bAddOverwriteLCO)
3809 {
3810 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "OVERWRITE", "ON");
3811 CPLDebug("GDALVectorTranslate", "Using OVERWRITE=ON");
3812 }
3813
3814 if( m_bNativeData &&
3815 poSrcLayer->GetMetadataItem("NATIVE_DATA", "NATIVE_DATA") != nullptr &&
3816 poSrcLayer->GetMetadataItem("NATIVE_MEDIA_TYPE", "NATIVE_DATA") != nullptr &&
3817 m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != nullptr &&
3818 strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "NATIVE_DATA") != nullptr &&
3819 strstr(m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST), "NATIVE_MEDIA_TYPE") != nullptr )
3820 {
3821 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "NATIVE_DATA",
3822 poSrcLayer->GetMetadataItem("NATIVE_DATA", "NATIVE_DATA"));
3823 papszLCOTemp = CSLSetNameValue(papszLCOTemp, "NATIVE_MEDIA_TYPE",
3824 poSrcLayer->GetMetadataItem("NATIVE_MEDIA_TYPE", "NATIVE_DATA"));
3825 CPLDebug("GDALVectorTranslate", "Transferring layer NATIVE_DATA");
3826 }
3827
3828 OGRSpatialReference* poOutputSRSClone = nullptr;
3829 if( poOutputSRS != nullptr )
3830 {
3831 poOutputSRSClone = poOutputSRS->Clone();
3832 }
3833 poDstLayer = m_poDstDS->CreateLayer( pszNewLayerName, poOutputSRSClone,
3834 static_cast<OGRwkbGeometryType>(eGCreateLayerType),
3835 papszLCOTemp );
3836 CSLDestroy(papszLCOTemp);
3837
3838 if( poOutputSRSClone != nullptr )
3839 {
3840 poOutputSRSClone->Release();
3841 }
3842
3843 if( poDstLayer == nullptr )
3844 {
3845 return nullptr;
3846 }
3847
3848 if( m_bCopyMD )
3849 {
3850 char** papszDomains = poSrcLayer->GetMetadataDomainList();
3851 for(char** papszIter = papszDomains; papszIter && *papszIter; ++papszIter )
3852 {
3853 if( !EQUAL(*papszIter, "IMAGE_STRUCTURE") &&
3854 !EQUAL(*papszIter, "SUBDATASETS") )
3855 {
3856 char** papszMD = poSrcLayer->GetMetadata(*papszIter);
3857 if( papszMD )
3858 poDstLayer->SetMetadata(papszMD, *papszIter);
3859 }
3860 }
3861 CSLDestroy(papszDomains);
3862 }
3863
3864 if( anRequestedGeomFields.empty() &&
3865 nSrcGeomFieldCount > 1 &&
3866 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
3867 {
3868 for(int i = 0; i < nSrcGeomFieldCount; i ++)
3869 {
3870 anRequestedGeomFields.push_back(i);
3871 }
3872 }
3873
3874 if( anRequestedGeomFields.size() > 1 ||
3875 (anRequestedGeomFields.size() == 1 &&
3876 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer)) )
3877 {
3878 for( int i = 0; i < static_cast<int>(anRequestedGeomFields.size());
3879 i++ )
3880 {
3881 const int iSrcGeomField = anRequestedGeomFields[i];
3882 OGRGeomFieldDefn oGFldDefn
3883 (poSrcFDefn->GetGeomFieldDefn(iSrcGeomField));
3884 if( m_poOutputSRS != nullptr )
3885 {
3886 poOutputSRSClone = m_poOutputSRS->Clone();
3887 oGFldDefn.SetSpatialRef(poOutputSRSClone);
3888 poOutputSRSClone->Release();
3889 }
3890 if( bForceGType )
3891 {
3892 oGFldDefn.SetType(static_cast<OGRwkbGeometryType>(eGType));
3893 }
3894 else
3895 {
3896 eGType = oGFldDefn.GetType();
3897 eGType = ConvertType(
3898 m_eGeomTypeConversion,
3899 static_cast<OGRwkbGeometryType>(eGType));
3900 eGType = ForceCoordDimension(eGType, m_nCoordDim);
3901 oGFldDefn.SetType(static_cast<OGRwkbGeometryType>(eGType));
3902 }
3903 if( m_bForceNullable )
3904 oGFldDefn.SetNullable(TRUE);
3905 poDstLayer->CreateGeomField(&oGFldDefn);
3906 }
3907 }
3908
3909 bAppend = false;
3910 }
3911
3912 /* -------------------------------------------------------------------- */
3913 /* Otherwise we will append to it, if append was requested. */
3914 /* -------------------------------------------------------------------- */
3915 else if( !bAppend && !m_bNewDataSource )
3916 {
3917 CPLError( CE_Failure, CPLE_AppDefined, "Layer %s already exists, and -append not specified.\n"
3918 " Consider using -append, or -overwrite.",
3919 pszNewLayerName );
3920 return nullptr;
3921 }
3922 else
3923 {
3924 if( CSLCount(m_papszLCO) > 0 )
3925 {
3926 CPLError( CE_Warning, CPLE_AppDefined, "Layer creation options ignored since an existing layer is\n"
3927 " being appended to." );
3928 }
3929 }
3930
3931 /* -------------------------------------------------------------------- */
3932 /* Process Layer style table */
3933 /* -------------------------------------------------------------------- */
3934
3935 poDstLayer->SetStyleTable( poSrcLayer->GetStyleTable () );
3936 /* -------------------------------------------------------------------- */
3937 /* Add fields. Default to copy all field. */
3938 /* If only a subset of all fields requested, then output only */
3939 /* the selected fields, and in the order that they were */
3940 /* selected. */
3941 /* -------------------------------------------------------------------- */
3942 const int nSrcFieldCount = poSrcFDefn->GetFieldCount();
3943 int iSrcFIDField = -1;
3944
3945 // Initialize the index-to-index map to -1's
3946 std::vector<int> anMap(nSrcFieldCount, -1);
3947
3948 std::map<int, TargetLayerInfo::ResolvedInfo> oMapResolved;
3949
3950 /* Caution : at the time of writing, the MapInfo driver */
3951 /* returns NULL until a field has been added */
3952 OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
3953
3954 if (m_papszFieldMap && bAppend)
3955 {
3956 bool bIdentity = false;
3957
3958 if (EQUAL(m_papszFieldMap[0], "identity"))
3959 bIdentity = true;
3960 else if (CSLCount(m_papszFieldMap) != nSrcFieldCount)
3961 {
3962 CPLError( CE_Failure, CPLE_AppDefined, "Field map should contain the value 'identity' or "
3963 "the same number of integer values as the source field count.");
3964 return nullptr;
3965 }
3966
3967 for( int iField=0; iField < nSrcFieldCount; iField++)
3968 {
3969 anMap[iField] = bIdentity? iField : atoi(m_papszFieldMap[iField]);
3970 if (anMap[iField] >= poDstFDefn->GetFieldCount())
3971 {
3972 CPLError( CE_Failure, CPLE_AppDefined, "Invalid destination field index %d.", anMap[iField]);
3973 return nullptr;
3974 }
3975 }
3976 }
3977 else if (m_papszSelFields && !bAppend )
3978 {
3979 int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
3980 for( int iField=0; m_papszSelFields[iField] != nullptr; iField++)
3981 {
3982 const int iSrcField =
3983 poSrcFDefn->GetFieldIndex(m_papszSelFields[iField]);
3984 if (iSrcField >= 0)
3985 {
3986 OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iSrcField);
3987 OGRFieldDefn oFieldDefn( poSrcFieldDefn );
3988
3989 DoFieldTypeConversion(m_poDstDS, oFieldDefn,
3990 m_papszFieldTypesToString,
3991 m_papszMapFieldType,
3992 m_bUnsetFieldWidth,
3993 psOptions->bQuiet,
3994 m_bForceNullable,
3995 m_bUnsetDefault);
3996
3997 /* The field may have been already created at layer creation */
3998 const int iDstField =
3999 poDstFDefn
4000 ? poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef())
4001 : -1;
4002 if (iDstField >= 0)
4003 {
4004 anMap[iSrcField] = iDstField;
4005 }
4006 else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
4007 {
4008 /* now that we've created a field, GetLayerDefn() won't return NULL */
4009 if (poDstFDefn == nullptr)
4010 poDstFDefn = poDstLayer->GetLayerDefn();
4011
4012 /* Sanity check : if it fails, the driver is buggy */
4013 if (poDstFDefn != nullptr &&
4014 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
4015 {
4016 CPLError(CE_Warning, CPLE_AppDefined,
4017 "The output driver has claimed to have added the %s field, but it did not!",
4018 oFieldDefn.GetNameRef() );
4019 }
4020 else
4021 {
4022 anMap[iSrcField] = nDstFieldCount;
4023 nDstFieldCount ++;
4024 }
4025 }
4026 }
4027 }
4028
4029 /* -------------------------------------------------------------------- */
4030 /* Use SetIgnoredFields() on source layer if available */
4031 /* -------------------------------------------------------------------- */
4032 if (poSrcLayer->TestCapability(OLCIgnoreFields))
4033 {
4034 bool bUseIgnoredFields = true;
4035 char** papszWHEREUsedFields = nullptr;
4036
4037 if (m_pszWHERE)
4038 {
4039 /* We must not ignore fields used in the -where expression (#4015) */
4040 OGRFeatureQuery oFeatureQuery;
4041 if ( oFeatureQuery.Compile( poSrcLayer->GetLayerDefn(), m_pszWHERE, FALSE, nullptr ) == OGRERR_NONE )
4042 {
4043 papszWHEREUsedFields = oFeatureQuery.GetUsedFields();
4044 }
4045 else
4046 {
4047 bUseIgnoredFields = false;
4048 }
4049 }
4050
4051 char** papszIgnoredFields = nullptr;
4052
4053 for(int iSrcField=0;
4054 bUseIgnoredFields && iSrcField<poSrcFDefn->GetFieldCount();
4055 iSrcField++)
4056 {
4057 const char* pszFieldName =
4058 poSrcFDefn->GetFieldDefn(iSrcField)->GetNameRef();
4059 bool bFieldRequested = false;
4060 for( int iField=0; m_papszSelFields[iField] != nullptr; iField++)
4061 {
4062 if (EQUAL(pszFieldName, m_papszSelFields[iField]))
4063 {
4064 bFieldRequested = true;
4065 break;
4066 }
4067 }
4068 bFieldRequested |= CSLFindString(papszWHEREUsedFields, pszFieldName) >= 0;
4069 bFieldRequested |= (m_pszZField != nullptr && EQUAL(pszFieldName, m_pszZField));
4070
4071 /* If source field not requested, add it to ignored files list */
4072 if (!bFieldRequested)
4073 papszIgnoredFields = CSLAddString(papszIgnoredFields, pszFieldName);
4074 }
4075 if (bUseIgnoredFields)
4076 poSrcLayer->SetIgnoredFields(const_cast<const char**>(papszIgnoredFields));
4077 CSLDestroy(papszIgnoredFields);
4078 CSLDestroy(papszWHEREUsedFields);
4079 }
4080 }
4081 else if( !bAppend || m_bAddMissingFields )
4082 {
4083 int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
4084
4085 const bool caseInsensitive =
4086 !EQUAL(m_poDstDS->GetDriver()->GetDescription(), "GeoJSON");
4087 auto formatName = [caseInsensitive](const char* name) {
4088 if( caseInsensitive ) {
4089 return CPLString(name).toupper();
4090 } else {
4091 return CPLString(name);
4092 }
4093 };
4094
4095 /* Save the map of existing fields, before creating new ones */
4096 /* This helps when converting a source layer that has duplicated field names */
4097 /* which is a bad idea */
4098 std::map<CPLString, int> oMapPreExistingFields;
4099 std::unordered_set<std::string> oSetDstFieldNames;
4100 for( int iField = 0; iField < nDstFieldCount; iField++ )
4101 {
4102 const char* pszFieldName = poDstFDefn->GetFieldDefn(iField)->GetNameRef();
4103 CPLString osUpperFieldName(formatName(pszFieldName));
4104 oSetDstFieldNames.insert(osUpperFieldName);
4105 if( oMapPreExistingFields.find(osUpperFieldName) ==
4106 oMapPreExistingFields.end() )
4107 oMapPreExistingFields[osUpperFieldName] = iField;
4108 /*else
4109 CPLError(CE_Warning, CPLE_AppDefined,
4110 "The target layer has already a duplicated field name '%s' before "
4111 "adding the fields of the source layer", pszFieldName); */
4112 }
4113
4114 const char* pszFIDColumn = poDstLayer->GetFIDColumn();
4115
4116 std::vector<int> anSrcFieldIndices;
4117 if( m_papszSelFields )
4118 {
4119 for( int iField=0; m_papszSelFields[iField] != nullptr; iField++)
4120 {
4121 const int iSrcField =
4122 poSrcFDefn->GetFieldIndex(m_papszSelFields[iField]);
4123 if (iSrcField >= 0)
4124 {
4125 anSrcFieldIndices.push_back(iSrcField);
4126 }
4127 }
4128 }
4129 else
4130 {
4131 for( int iField = 0; iField < nSrcFieldCount; iField++ )
4132 {
4133 anSrcFieldIndices.push_back(iField);
4134 }
4135 }
4136
4137 std::unordered_set<std::string> oSetSrcFieldNames;
4138 for( int i = 0; i < poSrcFDefn->GetFieldCount(); i++ )
4139 {
4140 oSetSrcFieldNames.insert(
4141 formatName(poSrcFDefn->GetFieldDefn(i)->GetNameRef()));
4142 }
4143
4144 for( size_t i = 0; i < anSrcFieldIndices.size(); i++ )
4145 {
4146 const int iField = anSrcFieldIndices[i];
4147 const OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
4148 OGRFieldDefn oFieldDefn( poSrcFieldDefn );
4149
4150 // Avoid creating a field with the same name as the FID column
4151 if( pszFIDColumn != nullptr && EQUAL(pszFIDColumn, oFieldDefn.GetNameRef()) &&
4152 (oFieldDefn.GetType() == OFTInteger || oFieldDefn.GetType() == OFTInteger64) )
4153 {
4154 iSrcFIDField = iField;
4155 continue;
4156 }
4157
4158 DoFieldTypeConversion(m_poDstDS, oFieldDefn,
4159 m_papszFieldTypesToString,
4160 m_papszMapFieldType,
4161 m_bUnsetFieldWidth,
4162 psOptions->bQuiet,
4163 m_bForceNullable,
4164 m_bUnsetDefault);
4165
4166 /* The field may have been already created at layer creation */
4167 std::map<CPLString, int>::iterator oIter =
4168 oMapPreExistingFields.find(formatName(oFieldDefn.GetNameRef()));
4169 if( oIter != oMapPreExistingFields.end() )
4170 {
4171 anMap[iField] = oIter->second;
4172 continue;
4173 }
4174
4175 bool bHasRenamed = false;
4176 /* In case the field name already exists in the target layer, */
4177 /* build a unique field name */
4178 if( oSetDstFieldNames.find(
4179 formatName(oFieldDefn.GetNameRef())) !=
4180 oSetDstFieldNames.end() )
4181 {
4182 int nTry = 1;
4183 CPLString osTmpNameRaddixUC(oFieldDefn.GetNameRef());
4184 osTmpNameRaddixUC = formatName(osTmpNameRaddixUC);
4185 CPLString osTmpNameUC = osTmpNameRaddixUC;
4186 osTmpNameUC.reserve(osTmpNameUC.size() + 10);
4187 while( true )
4188 {
4189 ++nTry;
4190 char szTry[32];
4191 snprintf(szTry, sizeof(szTry), "%d", nTry);
4192 osTmpNameUC.replace(osTmpNameRaddixUC.size(), std::string::npos, szTry);
4193
4194 /* Check that the proposed name doesn't exist either in the already */
4195 /* created fields or in the source fields */
4196 if( oSetDstFieldNames.find(osTmpNameUC) ==
4197 oSetDstFieldNames.end() &&
4198 oSetSrcFieldNames.find(osTmpNameUC) ==
4199 oSetSrcFieldNames.end() )
4200 {
4201 bHasRenamed = true;
4202 oFieldDefn.SetName((CPLString(oFieldDefn.GetNameRef()) + szTry).c_str());
4203 break;
4204 }
4205 }
4206 }
4207
4208 // Create field domain in output dataset if not already existing.
4209 const auto osDomainName = oFieldDefn.GetDomainName();
4210 if( !osDomainName.empty() )
4211 {
4212 if( m_poDstDS->TestCapability(ODsCAddFieldDomain) &&
4213 m_poDstDS->GetFieldDomain(osDomainName) == nullptr )
4214 {
4215 const auto poSrcDomain =
4216 m_poSrcDS->GetFieldDomain(osDomainName);
4217 if( poSrcDomain )
4218 {
4219 std::string failureReason;
4220 if( !m_poDstDS->AddFieldDomain(
4221 std::unique_ptr<OGRFieldDomain>(poSrcDomain->Clone()),
4222 failureReason) )
4223 {
4224 oFieldDefn.SetDomainName(std::string());
4225 CPLDebug("OGR2OGR", "Cannot create domain %s: %s",
4226 osDomainName.c_str(), failureReason.c_str());
4227 }
4228 }
4229 else
4230 {
4231 CPLDebug("OGR2OGR",
4232 "Cannot find domain %s in source dataset",
4233 osDomainName.c_str());
4234 }
4235 }
4236 if( m_poDstDS->GetFieldDomain(osDomainName) == nullptr )
4237 {
4238 oFieldDefn.SetDomainName(std::string());
4239 }
4240 }
4241
4242 if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
4243 {
4244 /* now that we've created a field, GetLayerDefn() won't return NULL */
4245 if (poDstFDefn == nullptr)
4246 poDstFDefn = poDstLayer->GetLayerDefn();
4247
4248 /* Sanity check : if it fails, the driver is buggy */
4249 if (poDstFDefn != nullptr &&
4250 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
4251 {
4252 CPLError(CE_Warning, CPLE_AppDefined,
4253 "The output driver has claimed to have added the %s field, but it did not!",
4254 oFieldDefn.GetNameRef() );
4255 }
4256 else
4257 {
4258 if( poDstFDefn != nullptr )
4259 {
4260 const char* pszNewFieldName =
4261 poDstFDefn->GetFieldDefn(nDstFieldCount)->GetNameRef();
4262 if( bHasRenamed )
4263 {
4264 CPLError(CE_Warning, CPLE_AppDefined,
4265 "Field '%s' already exists. Renaming it as '%s'",
4266 poSrcFieldDefn->GetNameRef(), pszNewFieldName);
4267 }
4268 oSetDstFieldNames.insert(formatName(pszNewFieldName));
4269 }
4270
4271 anMap[iField] = nDstFieldCount;
4272 nDstFieldCount ++;
4273 }
4274 }
4275
4276 if( m_bResolveDomains && !osDomainName.empty() )
4277 {
4278 const auto poSrcDomain =
4279 m_poSrcDS->GetFieldDomain(osDomainName);
4280 if( poSrcDomain && poSrcDomain->GetDomainType() == OFDT_CODED )
4281 {
4282 OGRFieldDefn oResolvedField(
4283 CPLSPrintf("%s_resolved", oFieldDefn.GetNameRef()),
4284 OFTString );
4285 if (poDstLayer->CreateField( &oResolvedField ) == OGRERR_NONE)
4286 {
4287 TargetLayerInfo::ResolvedInfo resolvedInfo;
4288 resolvedInfo.nSrcField = iField;
4289 resolvedInfo.poDomain = poSrcDomain;
4290 oMapResolved[nDstFieldCount] = resolvedInfo;
4291 nDstFieldCount ++;
4292 }
4293 }
4294 }
4295 }
4296 }
4297 else
4298 {
4299 /* For an existing layer, build the map by fetching the index in the destination */
4300 /* layer for each source field */
4301 if (poDstFDefn == nullptr)
4302 {
4303 CPLError( CE_Failure, CPLE_AppDefined, "poDstFDefn == NULL." );
4304 return nullptr;
4305 }
4306
4307 for( int iField = 0; iField < nSrcFieldCount; iField++ )
4308 {
4309 OGRFieldDefn* poSrcFieldDefn = poSrcFDefn->GetFieldDefn(iField);
4310 const int iDstField =
4311 poDstLayer->FindFieldIndex(poSrcFieldDefn->GetNameRef(),
4312 m_bExactFieldNameMatch);
4313 if (iDstField >= 0)
4314 anMap[iField] = iDstField;
4315 else
4316 CPLDebug("GDALVectorTranslate", "Skipping field '%s' not found in destination layer '%s'.",
4317 poSrcFieldDefn->GetNameRef(), poDstLayer->GetName() );
4318 }
4319 }
4320
4321 if( bOverwriteActuallyDone && !bAddOverwriteLCO &&
4322 EQUAL(m_poDstDS->GetDriver()->GetDescription(), "PostgreSQL") &&
4323 !psOptions->nLayerTransaction &&
4324 psOptions->nGroupTransactions >= 0 &&
4325 CPLTestBool(CPLGetConfigOption("PG_COMMIT_WHEN_OVERWRITING", "YES")) )
4326 {
4327 CPLDebug("GDALVectorTranslate",
4328 "Forcing transaction commit as table overwriting occurred");
4329 // Commit when overwriting as this consumes a lot of PG resources
4330 // and could result in """out of shared memory.
4331 // You might need to increase max_locks_per_transaction."""" errors
4332 if( m_poDstDS->CommitTransaction() == OGRERR_FAILURE ||
4333 m_poDstDS->StartTransaction(psOptions->bForceTransaction) == OGRERR_FAILURE )
4334 {
4335 return nullptr;
4336 }
4337 nTotalEventsDone = 0;
4338 }
4339
4340 std::unique_ptr<TargetLayerInfo> psInfo(new TargetLayerInfo);
4341 psInfo->m_nFeaturesRead = 0;
4342 psInfo->m_bPerFeatureCT = false;
4343 psInfo->m_poSrcLayer = poSrcLayer;
4344 psInfo->m_poDstLayer = poDstLayer;
4345 psInfo->m_apoCT.resize(poDstLayer->GetLayerDefn()->GetGeomFieldCount());
4346 psInfo->m_aosTransformOptions.resize(poDstLayer->GetLayerDefn()->GetGeomFieldCount());
4347 psInfo->m_anMap = std::move(anMap);
4348 psInfo->m_iSrcZField = iSrcZField;
4349 psInfo->m_iSrcFIDField = iSrcFIDField;
4350 if( anRequestedGeomFields.size() == 1 )
4351 psInfo->m_iRequestedSrcGeomField = anRequestedGeomFields[0];
4352 else
4353 psInfo->m_iRequestedSrcGeomField = -1;
4354 psInfo->m_bPreserveFID = bPreserveFID;
4355 psInfo->m_pszCTPipeline = m_pszCTPipeline;
4356 psInfo->m_oMapResolved = std::move(oMapResolved);
4357 for( const auto& kv: psInfo->m_oMapResolved )
4358 {
4359 const auto poDomain = kv.second.poDomain;
4360 const auto poCodedDomain =
4361 cpl::down_cast<const OGRCodedFieldDomain*>(poDomain);
4362 const auto enumeration = poCodedDomain->GetEnumeration();
4363 std::map<std::string, std::string> oMapCodeValue;
4364 for( int i = 0; enumeration[i].pszCode != nullptr; ++i )
4365 {
4366 oMapCodeValue[enumeration[i].pszCode] =
4367 enumeration[i].pszValue ? enumeration[i].pszValue : "";
4368 }
4369 psInfo->m_oMapDomainToKV[poDomain] = std::move(oMapCodeValue);
4370 }
4371
4372 return psInfo;
4373 }
4374
4375 /************************************************************************/
4376 /* SetupCT() */
4377 /************************************************************************/
4378
SetupCT(TargetLayerInfo * psInfo,OGRLayer * poSrcLayer,bool bTransform,bool bWrapDateline,const CPLString & osDateLineOffset,OGRSpatialReference * poUserSourceSRS,OGRFeature * poFeature,OGRSpatialReference * poOutputSRS,OGRCoordinateTransformation * poGCPCoordTrans)4379 static bool SetupCT( TargetLayerInfo* psInfo,
4380 OGRLayer* poSrcLayer,
4381 bool bTransform,
4382 bool bWrapDateline,
4383 const CPLString& osDateLineOffset,
4384 OGRSpatialReference* poUserSourceSRS,
4385 OGRFeature* poFeature,
4386 OGRSpatialReference* poOutputSRS,
4387 OGRCoordinateTransformation* poGCPCoordTrans)
4388 {
4389 OGRLayer *poDstLayer = psInfo->m_poDstLayer;
4390 const int nDstGeomFieldCount =
4391 poDstLayer->GetLayerDefn()->GetGeomFieldCount();
4392 for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
4393 {
4394 /* -------------------------------------------------------------------- */
4395 /* Setup coordinate transformation if we need it. */
4396 /* -------------------------------------------------------------------- */
4397 OGRSpatialReference* poSourceSRS = nullptr;
4398 OGRCoordinateTransformation* poCT = nullptr;
4399 char** papszTransformOptions = nullptr;
4400
4401 int iSrcGeomField;
4402 auto poDstGeomFieldDefn = poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);
4403 if( psInfo->m_iRequestedSrcGeomField >= 0 )
4404 {
4405 iSrcGeomField = psInfo->m_iRequestedSrcGeomField;
4406 }
4407 else
4408 {
4409 iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
4410 poDstGeomFieldDefn->GetNameRef());
4411 if( iSrcGeomField < 0 )
4412 {
4413 if( nDstGeomFieldCount == 1 &&
4414 poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
4415 {
4416 iSrcGeomField = 0;
4417 }
4418 else
4419 {
4420 continue;
4421 }
4422 }
4423 }
4424
4425 if( psInfo->m_nFeaturesRead == 0 )
4426 {
4427 poSourceSRS = poUserSourceSRS;
4428 if( poSourceSRS == nullptr )
4429 {
4430 if( iSrcGeomField > 0 )
4431 poSourceSRS = poSrcLayer->GetLayerDefn()->
4432 GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
4433 else
4434 poSourceSRS = poSrcLayer->GetSpatialRef();
4435 }
4436 }
4437 if( poSourceSRS == nullptr )
4438 {
4439 OGRGeometry* poSrcGeometry =
4440 poFeature->GetGeomFieldRef(iSrcGeomField);
4441 if( poSrcGeometry )
4442 poSourceSRS = poSrcGeometry->getSpatialReference();
4443 psInfo->m_bPerFeatureCT = (bTransform || bWrapDateline);
4444 }
4445
4446 if( bTransform )
4447 {
4448 if( poSourceSRS == nullptr && psInfo->m_pszCTPipeline == nullptr )
4449 {
4450 CPLError( CE_Failure, CPLE_AppDefined, "Can't transform coordinates, source layer has no\n"
4451 "coordinate system. Use -s_srs to set one." );
4452
4453 return false;
4454 }
4455
4456 if( psInfo->m_pszCTPipeline == nullptr )
4457 {
4458 CPLAssert( nullptr != poSourceSRS );
4459 CPLAssert( nullptr != poOutputSRS );
4460 }
4461
4462 if( psInfo->m_apoCT[iGeom] != nullptr &&
4463 psInfo->m_apoCT[iGeom]->GetSourceCS() == poSourceSRS )
4464 {
4465 poCT = psInfo->m_apoCT[iGeom].get();
4466 }
4467 else
4468 {
4469 OGRCoordinateTransformationOptions options;
4470 if( psInfo->m_pszCTPipeline )
4471 {
4472 options.SetCoordinateOperation( psInfo->m_pszCTPipeline, false );
4473 }
4474 poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS, options );
4475 if( poCT == nullptr )
4476 {
4477 char *pszWKT = nullptr;
4478
4479 CPLError( CE_Failure, CPLE_AppDefined,
4480 "Failed to create coordinate transformation between the\n"
4481 "following coordinate systems. This may be because they\n"
4482 "are not transformable." );
4483
4484 if( poSourceSRS )
4485 {
4486 poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
4487 CPLError( CE_Failure, CPLE_AppDefined, "Source:\n%s", pszWKT );
4488 CPLFree(pszWKT);
4489 }
4490
4491 if( poOutputSRS )
4492 {
4493 poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
4494 CPLError( CE_Failure, CPLE_AppDefined, "Target:\n%s", pszWKT );
4495 CPLFree(pszWKT);
4496 }
4497
4498 return false;
4499 }
4500 poCT = new CompositeCT( poGCPCoordTrans, false, poCT, true );
4501 psInfo->m_apoCT[iGeom].reset(poCT);
4502 }
4503 }
4504 else
4505 {
4506 const char* const apszOptions[] = {
4507 "IGNORE_DATA_AXIS_TO_SRS_AXIS_MAPPING=YES",
4508 "CRITERION=EQUIVALENT", nullptr };
4509 auto poDstGeomFieldDefnSpatialRef = poDstGeomFieldDefn->GetSpatialRef();
4510 if( poSourceSRS && poDstGeomFieldDefnSpatialRef &&
4511 poSourceSRS->GetDataAxisToSRSAxisMapping() !=
4512 poDstGeomFieldDefnSpatialRef->GetDataAxisToSRSAxisMapping() &&
4513 poSourceSRS->IsSame(poDstGeomFieldDefnSpatialRef, apszOptions) )
4514 {
4515 psInfo->m_apoCT[iGeom].reset(new CompositeCT(
4516 new AxisMappingCoordinateTransformation(
4517 poSourceSRS->GetDataAxisToSRSAxisMapping(),
4518 poDstGeomFieldDefnSpatialRef->GetDataAxisToSRSAxisMapping()),
4519 true,
4520 poGCPCoordTrans,
4521 false));
4522 poCT = psInfo->m_apoCT[iGeom].get();
4523 }
4524 else if( poGCPCoordTrans )
4525 {
4526 psInfo->m_apoCT[iGeom].reset(new CompositeCT(
4527 poGCPCoordTrans, false, nullptr, false));
4528 poCT = psInfo->m_apoCT[iGeom].get();
4529 }
4530 }
4531
4532 if (bWrapDateline)
4533 {
4534 if (bTransform && poCT != nullptr && poOutputSRS != nullptr && poOutputSRS->IsGeographic())
4535 {
4536 papszTransformOptions =
4537 CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
4538 if( !osDateLineOffset.empty() )
4539 {
4540 CPLString soOffset("DATELINEOFFSET=");
4541 soOffset += osDateLineOffset;
4542 papszTransformOptions =
4543 CSLAddString(papszTransformOptions, soOffset);
4544 }
4545 }
4546 else if (poSourceSRS != nullptr && poSourceSRS->IsGeographic())
4547 {
4548 papszTransformOptions =
4549 CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
4550 if( !osDateLineOffset.empty() )
4551 {
4552 CPLString soOffset("DATELINEOFFSET=");
4553 soOffset += osDateLineOffset;
4554 papszTransformOptions =
4555 CSLAddString(papszTransformOptions, soOffset);
4556 }
4557 }
4558 else
4559 {
4560 static bool bHasWarned = false;
4561 if( !bHasWarned )
4562 CPLError( CE_Failure, CPLE_IllegalArg, "-wrapdateline option only works when reprojecting to a geographic SRS");
4563 bHasWarned = true;
4564 }
4565
4566 psInfo->m_aosTransformOptions[iGeom].Assign(papszTransformOptions);
4567 }
4568 }
4569 return true;
4570 }
4571
4572 /************************************************************************/
4573 /* LayerTranslator::Translate() */
4574 /************************************************************************/
4575
Translate(OGRFeature * poFeatureIn,TargetLayerInfo * psInfo,GIntBig nCountLayerFeatures,GIntBig * pnReadFeatureCount,GIntBig & nTotalEventsDone,GDALProgressFunc pfnProgress,void * pProgressArg,GDALVectorTranslateOptions * psOptions)4576 int LayerTranslator::Translate( OGRFeature* poFeatureIn,
4577 TargetLayerInfo* psInfo,
4578 GIntBig nCountLayerFeatures,
4579 GIntBig* pnReadFeatureCount,
4580 GIntBig& nTotalEventsDone,
4581 GDALProgressFunc pfnProgress,
4582 void *pProgressArg,
4583 GDALVectorTranslateOptions *psOptions )
4584 {
4585 const int eGType = m_eGType;
4586 OGRSpatialReference* poOutputSRS = m_poOutputSRS;
4587
4588 OGRLayer *poSrcLayer = psInfo->m_poSrcLayer;
4589 OGRLayer *poDstLayer = psInfo->m_poDstLayer;
4590 const int* const panMap = psInfo->m_anMap.data();
4591 const int iSrcZField = psInfo->m_iSrcZField;
4592 const bool bPreserveFID = psInfo->m_bPreserveFID;
4593 const int nSrcGeomFieldCount = poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
4594 const int nDstGeomFieldCount = poDstLayer->GetLayerDefn()->GetGeomFieldCount();
4595 const bool bExplodeCollections = m_bExplodeCollections && nDstGeomFieldCount <= 1;
4596 const int iRequestedSrcGeomField = psInfo->m_iRequestedSrcGeomField;
4597
4598 if( poOutputSRS == nullptr && !m_bNullifyOutputSRS )
4599 {
4600 if( nSrcGeomFieldCount == 1 )
4601 {
4602 poOutputSRS = poSrcLayer->GetSpatialRef();
4603 }
4604 else if( iRequestedSrcGeomField > 0 )
4605 {
4606 poOutputSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(
4607 iRequestedSrcGeomField)->GetSpatialRef();
4608 }
4609 }
4610
4611 /* -------------------------------------------------------------------- */
4612 /* Transfer features. */
4613 /* -------------------------------------------------------------------- */
4614 if( psOptions->nGroupTransactions )
4615 {
4616 if( psOptions->nLayerTransaction )
4617 {
4618 if( poDstLayer->StartTransaction() == OGRERR_FAILURE )
4619 return false;
4620 }
4621 }
4622
4623 OGRFeature *poFeature = nullptr;
4624 int nFeaturesInTransaction = 0;
4625 GIntBig nCount = 0; /* written + failed */
4626 GIntBig nFeaturesWritten = 0;
4627
4628 bool bRet = true;
4629 CPLErrorReset();
4630 while( true )
4631 {
4632 if( m_nLimit >= 0 && psInfo->m_nFeaturesRead >= m_nLimit )
4633 {
4634 break;
4635 }
4636
4637 if( poFeatureIn != nullptr )
4638 poFeature = poFeatureIn;
4639 else if( psOptions->nFIDToFetch != OGRNullFID )
4640 poFeature = poSrcLayer->GetFeature(psOptions->nFIDToFetch);
4641 else
4642 poFeature = poSrcLayer->GetNextFeature();
4643
4644 if( poFeature == nullptr )
4645 {
4646 if( CPLGetLastErrorType() == CE_Failure )
4647 {
4648 bRet = false;
4649 }
4650 break;
4651 }
4652
4653 if( psInfo->m_nFeaturesRead == 0 || psInfo->m_bPerFeatureCT )
4654 {
4655 if( !SetupCT( psInfo, poSrcLayer, m_bTransform, m_bWrapDateline,
4656 m_osDateLineOffset, m_poUserSourceSRS,
4657 poFeature, poOutputSRS, m_poGCPCoordTrans) )
4658 {
4659 OGRFeature::DestroyFeature( poFeature );
4660 return false;
4661 }
4662 }
4663
4664 psInfo->m_nFeaturesRead ++;
4665
4666 int nIters = 1;
4667 std::unique_ptr<OGRGeometryCollection> poCollToExplode;
4668 int iGeomCollToExplode = -1;
4669 if (bExplodeCollections)
4670 {
4671 OGRGeometry* poSrcGeometry;
4672 if( iRequestedSrcGeomField >= 0 )
4673 poSrcGeometry = poFeature->GetGeomFieldRef(
4674 iRequestedSrcGeomField);
4675 else
4676 poSrcGeometry = poFeature->GetGeometryRef();
4677 if (poSrcGeometry &&
4678 OGR_GT_IsSubClassOf(poSrcGeometry->getGeometryType(), wkbGeometryCollection) )
4679 {
4680 const int nParts = poSrcGeometry->toGeometryCollection()->getNumGeometries();
4681 if( nParts > 0 )
4682 {
4683 iGeomCollToExplode = iRequestedSrcGeomField >= 0 ?
4684 iRequestedSrcGeomField : 0;
4685 poCollToExplode.reset(
4686 poFeature->StealGeometry(iGeomCollToExplode)->toGeometryCollection());
4687 nIters = nParts;
4688 }
4689 }
4690 }
4691
4692 OGRFeature *poDstFeature = nullptr;
4693 for(int iPart = 0; iPart < nIters; iPart++)
4694 {
4695 if( psOptions->nLayerTransaction &&
4696 ++nFeaturesInTransaction == psOptions->nGroupTransactions )
4697 {
4698 if( poDstLayer->CommitTransaction() == OGRERR_FAILURE ||
4699 poDstLayer->StartTransaction() == OGRERR_FAILURE )
4700 {
4701 OGRFeature::DestroyFeature( poFeature );
4702 return false;
4703 }
4704 nFeaturesInTransaction = 0;
4705 }
4706 else if( !psOptions->nLayerTransaction &&
4707 psOptions->nGroupTransactions >= 0 &&
4708 ++nTotalEventsDone >= psOptions->nGroupTransactions )
4709 {
4710 if( m_poODS->CommitTransaction() == OGRERR_FAILURE ||
4711 m_poODS->StartTransaction(psOptions->bForceTransaction) == OGRERR_FAILURE )
4712 {
4713 OGRFeature::DestroyFeature( poFeature );
4714 return false;
4715 }
4716 nTotalEventsDone = 0;
4717 }
4718
4719 CPLErrorReset();
4720 poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
4721
4722 /* Optimization to avoid duplicating the source geometry in the */
4723 /* target feature : we steal it from the source feature for now... */
4724 OGRGeometry* poStolenGeometry = nullptr;
4725 if( !bExplodeCollections && nSrcGeomFieldCount == 1 &&
4726 (nDstGeomFieldCount == 1 ||
4727 (nDstGeomFieldCount == 0 && m_poClipSrc)) )
4728 {
4729 poStolenGeometry = poFeature->StealGeometry();
4730 }
4731 else if( !bExplodeCollections &&
4732 iRequestedSrcGeomField >= 0 )
4733 {
4734 poStolenGeometry = poFeature->StealGeometry(
4735 iRequestedSrcGeomField);
4736 }
4737
4738 if( nDstGeomFieldCount == 0 && poStolenGeometry && m_poClipSrc )
4739 {
4740 OGRGeometry* poClipped = poStolenGeometry->Intersection(m_poClipSrc);
4741 delete poStolenGeometry;
4742 poStolenGeometry = nullptr;
4743 if (poClipped == nullptr || poClipped->IsEmpty())
4744 {
4745 delete poClipped;
4746 goto end_loop;
4747 }
4748 delete poClipped;
4749 }
4750
4751 if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
4752 {
4753 if( psOptions->nGroupTransactions )
4754 {
4755 if( psOptions->nLayerTransaction )
4756 {
4757 if( poDstLayer->CommitTransaction() != OGRERR_NONE )
4758 {
4759 OGRFeature::DestroyFeature( poFeature );
4760 OGRFeature::DestroyFeature( poDstFeature );
4761 OGRGeometryFactory::destroyGeometry( poStolenGeometry );
4762 return false;
4763 }
4764 }
4765 }
4766
4767 CPLError( CE_Failure, CPLE_AppDefined,
4768 "Unable to translate feature " CPL_FRMT_GIB " from layer %s.",
4769 poFeature->GetFID(), poSrcLayer->GetName() );
4770
4771 OGRFeature::DestroyFeature( poFeature );
4772 OGRFeature::DestroyFeature( poDstFeature );
4773 OGRGeometryFactory::destroyGeometry( poStolenGeometry );
4774 return false;
4775 }
4776
4777 if (psOptions->bEmptyStrAsNull) {
4778 for( int i=0; i < poDstFeature->GetFieldCount(); i++ )
4779 {
4780 if (!poDstFeature->IsFieldSetAndNotNull(i))
4781 continue;
4782 auto fieldDef = poDstFeature->GetFieldDefnRef(i);
4783 if (fieldDef->GetType() != OGRFieldType::OFTString)
4784 continue;
4785 auto str = poDstFeature->GetFieldAsString(i);
4786 if (strcmp(str, "") == 0)
4787 poDstFeature->SetFieldNull(i);
4788 }
4789 }
4790
4791 /* ... and now we can attach the stolen geometry */
4792 if( poStolenGeometry )
4793 {
4794 poDstFeature->SetGeometryDirectly(poStolenGeometry);
4795 }
4796
4797 if( bPreserveFID )
4798 poDstFeature->SetFID( poFeature->GetFID() );
4799 else if( psInfo->m_iSrcFIDField >= 0 &&
4800 poFeature->IsFieldSetAndNotNull(psInfo->m_iSrcFIDField))
4801 poDstFeature->SetFID( poFeature->GetFieldAsInteger64(psInfo->m_iSrcFIDField) );
4802
4803 /* Erase native data if asked explicitly */
4804 if( !m_bNativeData )
4805 {
4806 poDstFeature->SetNativeData(nullptr);
4807 poDstFeature->SetNativeMediaType(nullptr);
4808 }
4809
4810 for( int iGeom = 0; iGeom < nDstGeomFieldCount; iGeom ++ )
4811 {
4812 OGRGeometry* poDstGeometry;
4813
4814 if( poCollToExplode && iGeom == iGeomCollToExplode )
4815 {
4816 OGRGeometry* poPart = poCollToExplode->getGeometryRef(0);
4817 poCollToExplode->removeGeometry(0, FALSE);
4818 poDstGeometry = poPart;
4819 assert(poDstGeometry);
4820 }
4821 else
4822 {
4823 poDstGeometry = poDstFeature->StealGeometry(iGeom);
4824 if (poDstGeometry == nullptr)
4825 continue;
4826 }
4827
4828 if (iSrcZField != -1)
4829 {
4830 SetZ(poDstGeometry, poFeature->GetFieldAsDouble(iSrcZField));
4831 /* This will correct the coordinate dimension to 3 */
4832 OGRGeometry* poDupGeometry = poDstGeometry->clone();
4833 delete poDstGeometry;
4834 poDstGeometry = poDupGeometry;
4835 }
4836
4837 if (m_nCoordDim == 2 || m_nCoordDim == 3)
4838 {
4839 poDstGeometry->setCoordinateDimension( m_nCoordDim );
4840 }
4841 else if (m_nCoordDim == 4)
4842 {
4843 poDstGeometry->set3D( TRUE );
4844 poDstGeometry->setMeasured( TRUE );
4845 }
4846 else if (m_nCoordDim == COORD_DIM_XYM)
4847 {
4848 poDstGeometry->set3D( FALSE );
4849 poDstGeometry->setMeasured( TRUE );
4850 }
4851 else if ( m_nCoordDim == COORD_DIM_LAYER_DIM )
4852 {
4853 const OGRwkbGeometryType eDstLayerGeomType =
4854 poDstLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom)->GetType();
4855 poDstGeometry->set3D( wkbHasZ(eDstLayerGeomType) );
4856 poDstGeometry->setMeasured( wkbHasM(eDstLayerGeomType) );
4857 }
4858
4859 if (m_eGeomOp == GEOMOP_SEGMENTIZE)
4860 {
4861 if (m_dfGeomOpParam > 0)
4862 poDstGeometry->segmentize(m_dfGeomOpParam);
4863 }
4864 else if (m_eGeomOp == GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY)
4865 {
4866 if (m_dfGeomOpParam > 0)
4867 {
4868 OGRGeometry* poNewGeom = poDstGeometry->SimplifyPreserveTopology(m_dfGeomOpParam);
4869 if (poNewGeom)
4870 {
4871 delete poDstGeometry;
4872 poDstGeometry = poNewGeom;
4873 }
4874 }
4875 }
4876
4877 if (m_poClipSrc)
4878 {
4879 OGRGeometry* poClipped = poDstGeometry->Intersection(m_poClipSrc);
4880 delete poDstGeometry;
4881 if (poClipped == nullptr || poClipped->IsEmpty())
4882 {
4883 delete poClipped;
4884 goto end_loop;
4885 }
4886 poDstGeometry = poClipped;
4887 }
4888
4889 OGRCoordinateTransformation* const poCT = psInfo->m_apoCT[iGeom].get();
4890 char** const papszTransformOptions = psInfo->m_aosTransformOptions[iGeom].List();
4891
4892 if( poCT != nullptr || papszTransformOptions != nullptr)
4893 {
4894 OGRGeometry* poReprojectedGeom =
4895 OGRGeometryFactory::transformWithOptions(
4896 poDstGeometry, poCT, papszTransformOptions, m_transformWithOptionsCache);
4897 if( poReprojectedGeom == nullptr )
4898 {
4899 if( psOptions->nGroupTransactions )
4900 {
4901 if( psOptions->nLayerTransaction )
4902 {
4903 if( poDstLayer->CommitTransaction() != OGRERR_NONE &&
4904 !psOptions->bSkipFailures )
4905 {
4906 OGRFeature::DestroyFeature( poFeature );
4907 OGRFeature::DestroyFeature( poDstFeature );
4908 delete poDstGeometry;
4909 return false;
4910 }
4911 }
4912 }
4913
4914 CPLError( CE_Failure, CPLE_AppDefined, "Failed to reproject feature " CPL_FRMT_GIB " (geometry probably out of source or destination SRS).",
4915 poFeature->GetFID() );
4916 if( !psOptions->bSkipFailures )
4917 {
4918 OGRFeature::DestroyFeature( poFeature );
4919 OGRFeature::DestroyFeature( poDstFeature );
4920 delete poDstGeometry;
4921 return false;
4922 }
4923 }
4924
4925 delete poDstGeometry;
4926 poDstGeometry = poReprojectedGeom;
4927 }
4928 else if (poOutputSRS != nullptr)
4929 {
4930 poDstGeometry->assignSpatialReference(poOutputSRS);
4931 }
4932
4933 if( poDstGeometry != nullptr )
4934 {
4935 if (m_poClipDst)
4936 {
4937 OGRGeometry* poClipped = poDstGeometry->Intersection(m_poClipDst);
4938 delete poDstGeometry;
4939 if (poClipped == nullptr || poClipped->IsEmpty())
4940 {
4941 delete poClipped;
4942 goto end_loop;
4943 }
4944
4945 poDstGeometry = poClipped;
4946 }
4947
4948 if( m_bMakeValid )
4949 {
4950 OGRGeometry* poValidGeom = poDstGeometry->MakeValid();
4951 delete poDstGeometry;
4952 poDstGeometry = poValidGeom;
4953 if( poDstGeometry == nullptr )
4954 goto end_loop;
4955 OGRGeometry* poCleanedGeom =
4956 OGRGeometryFactory::removeLowerDimensionSubGeoms(poDstGeometry);
4957 delete poDstGeometry;
4958 poDstGeometry = poCleanedGeom;
4959 }
4960
4961 if( eGType != GEOMTYPE_UNCHANGED )
4962 {
4963 poDstGeometry = OGRGeometryFactory::forceTo(
4964 poDstGeometry, static_cast<OGRwkbGeometryType>(eGType));
4965 }
4966 else if( m_eGeomTypeConversion == GTC_PROMOTE_TO_MULTI ||
4967 m_eGeomTypeConversion == GTC_CONVERT_TO_LINEAR ||
4968 m_eGeomTypeConversion == GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR ||
4969 m_eGeomTypeConversion == GTC_CONVERT_TO_CURVE )
4970 {
4971 OGRwkbGeometryType eTargetType = poDstGeometry->getGeometryType();
4972 eTargetType = ConvertType(m_eGeomTypeConversion, eTargetType);
4973 poDstGeometry = OGRGeometryFactory::forceTo(poDstGeometry, eTargetType);
4974 }
4975 }
4976
4977 poDstFeature->SetGeomFieldDirectly(iGeom, poDstGeometry);
4978 }
4979
4980 if( !psInfo->m_oMapResolved.empty() )
4981 {
4982 for( const auto& kv: psInfo->m_oMapResolved )
4983 {
4984 const int nDstField = kv.first;
4985 const int nSrcField = kv.second.nSrcField;
4986 if( poFeature->IsFieldSetAndNotNull(nSrcField) )
4987 {
4988 const auto poDomain = kv.second.poDomain;
4989 const auto& oMapKV = psInfo->m_oMapDomainToKV[poDomain];
4990 const auto iter = oMapKV.find(
4991 poFeature->GetFieldAsString(nSrcField));
4992 if( iter != oMapKV.end() )
4993 {
4994 poDstFeature->SetField(nDstField, iter->second.c_str());
4995 }
4996 }
4997 }
4998 }
4999
5000 CPLErrorReset();
5001 if( poDstLayer->CreateFeature( poDstFeature ) == OGRERR_NONE )
5002 {
5003 nFeaturesWritten ++;
5004 if( (bPreserveFID && poDstFeature->GetFID() != poFeature->GetFID()) ||
5005 (!bPreserveFID && psInfo->m_iSrcFIDField >= 0 && poFeature->IsFieldSetAndNotNull(psInfo->m_iSrcFIDField) &&
5006 poDstFeature->GetFID() != poFeature->GetFieldAsInteger64(psInfo->m_iSrcFIDField)) )
5007 {
5008 CPLError( CE_Warning, CPLE_AppDefined,
5009 "Feature id not preserved");
5010 }
5011 }
5012 else if( !psOptions->bSkipFailures )
5013 {
5014 if( psOptions->nGroupTransactions )
5015 {
5016 if( psOptions->nLayerTransaction )
5017 poDstLayer->RollbackTransaction();
5018 }
5019
5020 CPLError( CE_Failure, CPLE_AppDefined,
5021 "Unable to write feature " CPL_FRMT_GIB " from layer %s.",
5022 poFeature->GetFID(), poSrcLayer->GetName() );
5023
5024 OGRFeature::DestroyFeature( poFeature );
5025 OGRFeature::DestroyFeature( poDstFeature );
5026 return false;
5027 }
5028 else
5029 {
5030 CPLDebug( "GDALVectorTranslate", "Unable to write feature " CPL_FRMT_GIB " into layer %s.",
5031 poFeature->GetFID(), poSrcLayer->GetName() );
5032 if( psOptions->nGroupTransactions )
5033 {
5034 if( psOptions->nLayerTransaction )
5035 {
5036 poDstLayer->RollbackTransaction();
5037 CPL_IGNORE_RET_VAL(poDstLayer->StartTransaction());
5038 }
5039 else
5040 {
5041 m_poODS->RollbackTransaction();
5042 m_poODS->StartTransaction(psOptions->bForceTransaction);
5043 }
5044 }
5045 }
5046
5047 end_loop:
5048 OGRFeature::DestroyFeature( poDstFeature );
5049 }
5050
5051 OGRFeature::DestroyFeature( poFeature );
5052
5053 /* Report progress */
5054 nCount ++;
5055 bool bGoOn = true;
5056 if (pfnProgress)
5057 {
5058 bGoOn = pfnProgress(nCountLayerFeatures ? nCount * 1.0 / nCountLayerFeatures: 1.0, "", pProgressArg) != FALSE;
5059 }
5060 if( !bGoOn )
5061 {
5062 bRet = false;
5063 break;
5064 }
5065
5066 if (pnReadFeatureCount)
5067 *pnReadFeatureCount = nCount;
5068
5069 if( psOptions->nFIDToFetch != OGRNullFID )
5070 break;
5071 if( poFeatureIn != nullptr )
5072 break;
5073 }
5074
5075 if( psOptions->nGroupTransactions )
5076 {
5077 if( psOptions->nLayerTransaction )
5078 {
5079 if( poDstLayer->CommitTransaction() != OGRERR_NONE )
5080 bRet = false;
5081 }
5082 }
5083
5084 if( poFeatureIn == nullptr )
5085 {
5086 CPLDebug("GDALVectorTranslate", CPL_FRMT_GIB " features written in layer '%s'",
5087 nFeaturesWritten, poDstLayer->GetName());
5088 }
5089
5090 return bRet;
5091 }
5092
5093 /************************************************************************/
5094 /* RemoveBOM() */
5095 /************************************************************************/
5096
5097 /* Remove potential UTF-8 BOM from data (must be NUL terminated) */
RemoveBOM(GByte * pabyData)5098 static void RemoveBOM(GByte* pabyData)
5099 {
5100 if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
5101 {
5102 memmove(pabyData, pabyData + 3, strlen(reinterpret_cast<char*>(pabyData) + 3) + 1);
5103 }
5104 }
5105
RemoveSQLComments(char * & pszSQL)5106 static void RemoveSQLComments(char*& pszSQL)
5107 {
5108 char** papszLines = CSLTokenizeStringComplex(pszSQL, "\r\n", FALSE, FALSE);
5109 CPLString osSQL;
5110 for( char** papszIter = papszLines; papszIter && *papszIter; ++papszIter )
5111 {
5112 const char* pszLine = *papszIter;
5113 char chQuote = 0;
5114 int i = 0;
5115 for(; pszLine[i] != '\0'; ++i )
5116 {
5117 if( chQuote )
5118 {
5119 if( pszLine[i] == chQuote )
5120 {
5121 if( pszLine[i+1] == chQuote )
5122 {
5123 i++;
5124 }
5125 else
5126 {
5127 chQuote = 0;
5128 }
5129 }
5130 }
5131 else if( pszLine[i] == '\'' || pszLine[i] == '"' )
5132 {
5133 chQuote = pszLine[i];
5134 }
5135 else if( pszLine[i] == '-' && pszLine[i+1] == '-' )
5136 {
5137 break;
5138 }
5139 }
5140 if( i > 0 )
5141 {
5142 osSQL.append(pszLine, i);
5143 }
5144 osSQL += ' ';
5145 }
5146 CSLDestroy(papszLines);
5147 CPLFree(pszSQL);
5148 pszSQL = CPLStrdup(osSQL);
5149 }
5150
5151 /************************************************************************/
5152 /* GDALVectorTranslateOptionsNew() */
5153 /************************************************************************/
5154
5155 /**
5156 * allocates a GDALVectorTranslateOptions struct.
5157 *
5158 * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
5159 * The accepted options are the ones of the <a href="/programs/ogr2ogr.html">ogr2ogr</a> utility.
5160 * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
5161 * otherwise (gdal_translate_bin.cpp use case) must be allocated with
5162 * GDALVectorTranslateOptionsForBinaryNew() prior to this function. Will be
5163 * filled with potentially present filename, open options,...
5164 * @return pointer to the allocated GDALVectorTranslateOptions struct. Must be freed with GDALVectorTranslateOptionsFree().
5165 *
5166 * @since GDAL 2.1
5167 */
GDALVectorTranslateOptionsNew(char ** papszArgv,GDALVectorTranslateOptionsForBinary * psOptionsForBinary)5168 GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(char** papszArgv,
5169 GDALVectorTranslateOptionsForBinary* psOptionsForBinary)
5170 {
5171 GDALVectorTranslateOptions *psOptions =
5172 static_cast<GDALVectorTranslateOptions *>(
5173 CPLCalloc( 1, sizeof(GDALVectorTranslateOptions)));
5174
5175 psOptions->eAccessMode = ACCESS_CREATION;
5176 psOptions->bSkipFailures = false;
5177 psOptions->nLayerTransaction = -1;
5178 psOptions->bForceTransaction = false;
5179 psOptions->nGroupTransactions = 100 * 1000;
5180 psOptions->nFIDToFetch = OGRNullFID;
5181 psOptions->bQuiet = false;
5182 psOptions->pszFormat = nullptr;
5183 psOptions->papszLayers = nullptr;
5184 psOptions->papszDSCO = nullptr;
5185 psOptions->papszLCO = nullptr;
5186 psOptions->bTransform = false;
5187 psOptions->bAddMissingFields = false;
5188 psOptions->pszOutputSRSDef = nullptr;
5189 psOptions->pszSourceSRSDef = nullptr;
5190 psOptions->pszCTPipeline = nullptr;
5191 psOptions->bNullifyOutputSRS = false;
5192 psOptions->bExactFieldNameMatch = true;
5193 psOptions->pszNewLayerName = nullptr;
5194 psOptions->pszWHERE = nullptr;
5195 psOptions->pszGeomField = nullptr;
5196 psOptions->papszSelFields = nullptr;
5197 psOptions->pszSQLStatement = nullptr;
5198 psOptions->pszDialect = nullptr;
5199 psOptions->eGType = GEOMTYPE_UNCHANGED;
5200 psOptions->eGeomTypeConversion = GTC_DEFAULT;
5201 psOptions->eGeomOp = GEOMOP_NONE;
5202 psOptions->dfGeomOpParam = 0;
5203 psOptions->bMakeValid = false;
5204 psOptions->papszFieldTypesToString = nullptr;
5205 psOptions->papszMapFieldType = nullptr;
5206 psOptions->bUnsetFieldWidth = false;
5207 psOptions->bDisplayProgress = false;
5208 psOptions->bWrapDateline = false;
5209 psOptions->dfDateLineOffset = 10.0;
5210 psOptions->bClipSrc = false;
5211 psOptions->hClipSrc = nullptr;
5212 psOptions->pszClipSrcDS = nullptr;
5213 psOptions->pszClipSrcSQL = nullptr;
5214 psOptions->pszClipSrcLayer = nullptr;
5215 psOptions->pszClipSrcWhere = nullptr;
5216 psOptions->hClipDst = nullptr;
5217 psOptions->pszClipDstDS = nullptr;
5218 psOptions->pszClipDstSQL = nullptr;
5219 psOptions->pszClipDstLayer = nullptr;
5220 psOptions->pszClipDstWhere = nullptr;
5221 psOptions->bSplitListFields = false;
5222 psOptions->nMaxSplitListSubFields = -1;
5223 psOptions->bExplodeCollections = false;
5224 psOptions->pszZField = nullptr;
5225 psOptions->papszFieldMap = nullptr;
5226 psOptions->nCoordDim = COORD_DIM_UNCHANGED;
5227 psOptions->papszDestOpenOptions = nullptr;
5228 psOptions->bForceNullable = false;
5229 psOptions->bResolveDomains = false;
5230 psOptions->bUnsetDefault = false;
5231 psOptions->bUnsetFid = false;
5232 psOptions->bPreserveFID = false;
5233 psOptions->bCopyMD = true;
5234 psOptions->papszMetadataOptions = nullptr;
5235 psOptions->pszSpatSRSDef = nullptr;
5236 psOptions->nGCPCount = 0;
5237 psOptions->pasGCPs = nullptr;
5238 psOptions->nTransformOrder = 0; /* Default to 0 for now... let the lib decide */
5239 psOptions->hSpatialFilter = nullptr;
5240 psOptions->bNativeData = true;
5241 psOptions->nLimit = -1;
5242
5243 int nArgc = CSLCount(papszArgv);
5244 for( int i = 0; papszArgv != nullptr && i < nArgc; i++ )
5245 {
5246 if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
5247 {
5248 if( psOptionsForBinary )
5249 psOptionsForBinary->bQuiet = TRUE;
5250 }
5251 else if( i+1 < nArgc && (EQUAL(papszArgv[i],"-f") || EQUAL(papszArgv[i],"-of")) )
5252 {
5253 CPLFree(psOptions->pszFormat);
5254 const char* pszFormatArg = papszArgv[++i];
5255 psOptions->pszFormat = CPLStrdup(pszFormatArg);
5256 }
5257 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-dsco") )
5258 {
5259 psOptions->papszDSCO = CSLAddString(psOptions->papszDSCO, papszArgv[++i] );
5260 }
5261 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-lco") )
5262 {
5263 psOptions->papszLCO = CSLAddString(psOptions->papszLCO, papszArgv[++i] );
5264 }
5265 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-oo") )
5266 {
5267 ++i;
5268 if( psOptionsForBinary )
5269 {
5270 psOptionsForBinary->papszOpenOptions = CSLAddString(psOptionsForBinary->papszOpenOptions, papszArgv[i] );
5271 }
5272 }
5273 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-doo") )
5274 {
5275 ++i;
5276 psOptions->papszDestOpenOptions = CSLAddString(psOptions->papszDestOpenOptions, papszArgv[i] );
5277 }
5278 else if( EQUAL(papszArgv[i],"-preserve_fid") )
5279 {
5280 psOptions->bPreserveFID = true;
5281 }
5282 else if( STARTS_WITH_CI(papszArgv[i], "-skip") )
5283 {
5284 psOptions->bSkipFailures = true;
5285 psOptions->nGroupTransactions = 1; /* #2409 */
5286 }
5287 else if( EQUAL(papszArgv[i],"-append") )
5288 {
5289 psOptions->eAccessMode = ACCESS_APPEND;
5290 }
5291 else if( EQUAL(papszArgv[i],"-overwrite") )
5292 {
5293 psOptions->eAccessMode = ACCESS_OVERWRITE;
5294 }
5295 else if( EQUAL(papszArgv[i],"-addfields") )
5296 {
5297 psOptions->bAddMissingFields = true;
5298 psOptions->eAccessMode = ACCESS_APPEND;
5299 }
5300 else if( EQUAL(papszArgv[i],"-update") )
5301 {
5302 /* Don't reset -append or -overwrite */
5303 if( psOptions->eAccessMode != ACCESS_APPEND && psOptions->eAccessMode != ACCESS_OVERWRITE )
5304 psOptions->eAccessMode = ACCESS_UPDATE;
5305 }
5306 else if( EQUAL(papszArgv[i],"-relaxedFieldNameMatch") )
5307 {
5308 psOptions->bExactFieldNameMatch = false;
5309 }
5310 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-fid") )
5311 {
5312 psOptions->nFIDToFetch = CPLAtoGIntBig(papszArgv[++i]);
5313 }
5314 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-sql") )
5315 {
5316 i++;
5317 CPLFree(psOptions->pszSQLStatement);
5318 GByte* pabyRet = nullptr;
5319 if( papszArgv[i][0] == '@' &&
5320 VSIIngestFile( nullptr, papszArgv[i] + 1, &pabyRet, nullptr, 1024*1024) )
5321 {
5322 RemoveBOM(pabyRet);
5323 psOptions->pszSQLStatement = reinterpret_cast<char*>(pabyRet);
5324 RemoveSQLComments(psOptions->pszSQLStatement);
5325 }
5326 else
5327 {
5328 psOptions->pszSQLStatement = CPLStrdup(papszArgv[i]);
5329 }
5330 }
5331 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-dialect") )
5332 {
5333 CPLFree(psOptions->pszDialect);
5334 psOptions->pszDialect = CPLStrdup(papszArgv[++i]);
5335 }
5336 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-nln") )
5337 {
5338 CPLFree(psOptions->pszNewLayerName);
5339 psOptions->pszNewLayerName = CPLStrdup(papszArgv[++i]);
5340 }
5341 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-nlt") )
5342 {
5343 bool bIs3D = false;
5344 CPLString osGeomName = papszArgv[i+1];
5345 if (strlen(papszArgv[i+1]) > 3 &&
5346 STARTS_WITH_CI(papszArgv[i+1] + strlen(papszArgv[i+1]) - 3, "25D"))
5347 {
5348 bIs3D = true;
5349 osGeomName.resize(osGeomName.size() - 3);
5350 }
5351 else if (strlen(papszArgv[i+1]) > 1 &&
5352 STARTS_WITH_CI(papszArgv[i+1] + strlen(papszArgv[i+1]) - 1, "Z"))
5353 {
5354 bIs3D = true;
5355 osGeomName.resize(osGeomName.size() - 1);
5356 }
5357 if( EQUAL(osGeomName,"NONE") )
5358 psOptions->eGType = wkbNone;
5359 else if( EQUAL(osGeomName,"GEOMETRY") )
5360 psOptions->eGType = wkbUnknown;
5361 else if( EQUAL(osGeomName,"PROMOTE_TO_MULTI") )
5362 {
5363 if( psOptions->eGeomTypeConversion == GTC_CONVERT_TO_LINEAR )
5364 psOptions->eGeomTypeConversion = GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR;
5365 else
5366 psOptions->eGeomTypeConversion = GTC_PROMOTE_TO_MULTI;
5367 }
5368 else if( EQUAL(osGeomName,"CONVERT_TO_LINEAR") )
5369 {
5370 if( psOptions->eGeomTypeConversion == GTC_PROMOTE_TO_MULTI )
5371 psOptions->eGeomTypeConversion = GTC_PROMOTE_TO_MULTI_AND_CONVERT_TO_LINEAR;
5372 else
5373 psOptions->eGeomTypeConversion = GTC_CONVERT_TO_LINEAR;
5374 }
5375 else if( EQUAL(osGeomName,"CONVERT_TO_CURVE") )
5376 psOptions->eGeomTypeConversion = GTC_CONVERT_TO_CURVE;
5377 else
5378 {
5379 psOptions->eGType = OGRFromOGCGeomType(osGeomName);
5380 if (psOptions->eGType == wkbUnknown)
5381 {
5382 CPLError(CE_Failure, CPLE_IllegalArg,
5383 "-nlt %s: type not recognised.",
5384 papszArgv[i+1] );
5385 GDALVectorTranslateOptionsFree(psOptions);
5386 return nullptr;
5387 }
5388 }
5389 if (psOptions->eGType != GEOMTYPE_UNCHANGED && psOptions->eGType != wkbNone && bIs3D)
5390 psOptions->eGType = wkbSetZ(static_cast<OGRwkbGeometryType>(psOptions->eGType));
5391
5392 i++;
5393 }
5394 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-dim") )
5395 {
5396 if( EQUAL(papszArgv[i+1], "layer_dim") )
5397 psOptions->nCoordDim = COORD_DIM_LAYER_DIM;
5398 else if( EQUAL(papszArgv[i+1], "XY") || EQUAL(papszArgv[i+1], "2") )
5399 psOptions->nCoordDim = 2;
5400 else if( EQUAL(papszArgv[i+1], "XYZ") || EQUAL(papszArgv[i+1], "3") )
5401 psOptions->nCoordDim = 3;
5402 else if( EQUAL(papszArgv[i+1], "XYM") )
5403 psOptions->nCoordDim = COORD_DIM_XYM;
5404 else if( EQUAL(papszArgv[i+1], "XYZM") )
5405 psOptions->nCoordDim = 4;
5406 else
5407 {
5408 CPLError(CE_Failure, CPLE_IllegalArg,"-dim %s: value not handled.",
5409 papszArgv[i+1] );
5410 GDALVectorTranslateOptionsFree(psOptions);
5411 return nullptr;
5412 }
5413 i++;
5414 }
5415 else if( i+1 < nArgc && (EQUAL(papszArgv[i],"-tg") ||
5416 EQUAL(papszArgv[i],"-gt")) )
5417 {
5418 ++i;
5419 /* If skipfailures is already set we should not
5420 modify nGroupTransactions = 1 #2409 */
5421 if ( !psOptions->bSkipFailures )
5422 {
5423 if( EQUAL(papszArgv[i], "unlimited") )
5424 psOptions->nGroupTransactions = -1;
5425 else
5426 psOptions->nGroupTransactions = atoi(papszArgv[i]);
5427 }
5428 }
5429 else if ( EQUAL(papszArgv[i],"-ds_transaction") )
5430 {
5431 psOptions->nLayerTransaction = FALSE;
5432 psOptions->bForceTransaction = true;
5433 }
5434 /* Undocumented. Just a provision. Default behavior should be OK */
5435 else if ( EQUAL(papszArgv[i],"-lyr_transaction") )
5436 {
5437 psOptions->nLayerTransaction = TRUE;
5438 }
5439 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-s_srs") )
5440 {
5441 CPLFree(psOptions->pszSourceSRSDef);
5442 psOptions->pszSourceSRSDef = CPLStrdup(papszArgv[++i]);
5443 }
5444 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-a_srs") )
5445 {
5446 CPLFree(psOptions->pszOutputSRSDef);
5447 psOptions->pszOutputSRSDef = CPLStrdup(papszArgv[++i]);
5448 if (EQUAL(psOptions->pszOutputSRSDef, "NULL") ||
5449 EQUAL(psOptions->pszOutputSRSDef, "NONE"))
5450 {
5451 psOptions->pszOutputSRSDef = nullptr;
5452 psOptions->bNullifyOutputSRS = true;
5453 }
5454 }
5455 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-t_srs") )
5456 {
5457 CPLFree(psOptions->pszOutputSRSDef);
5458 psOptions->pszOutputSRSDef = CPLStrdup(papszArgv[++i]);
5459 psOptions->bTransform = true;
5460 }
5461 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-ct") )
5462 {
5463 CPLFree(psOptions->pszCTPipeline);
5464 psOptions->pszCTPipeline = CPLStrdup(papszArgv[++i]);
5465 psOptions->bTransform = true;
5466 }
5467 else if( i+4 < nArgc && EQUAL(papszArgv[i],"-spat") )
5468 {
5469 OGRLinearRing oRing;
5470
5471 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5472 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
5473 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
5474 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
5475 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5476
5477 OGRPolygon* poSpatialFilter = new OGRPolygon();
5478 poSpatialFilter->addRing( &oRing );
5479 OGR_G_DestroyGeometry(psOptions->hSpatialFilter);
5480 psOptions->hSpatialFilter = reinterpret_cast<OGRGeometryH>(poSpatialFilter);
5481 i += 4;
5482 }
5483 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-spat_srs") )
5484 {
5485 CPLFree(psOptions->pszSpatSRSDef);
5486 psOptions->pszSpatSRSDef = CPLStrdup(papszArgv[++i]);
5487 }
5488 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-geomfield") )
5489 {
5490 CPLFree(psOptions->pszGeomField);
5491 psOptions->pszGeomField = CPLStrdup(papszArgv[++i]);
5492 }
5493 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-where") )
5494 {
5495 i++;
5496 CPLFree(psOptions->pszWHERE);
5497 GByte* pabyRet = nullptr;
5498 if( papszArgv[i][0] == '@' &&
5499 VSIIngestFile( nullptr, papszArgv[i] + 1, &pabyRet, nullptr, 1024*1024) )
5500 {
5501 RemoveBOM(pabyRet);
5502 psOptions->pszWHERE = reinterpret_cast<char*>(pabyRet);
5503 }
5504 else
5505 {
5506 psOptions->pszWHERE = CPLStrdup(papszArgv[i]);
5507 }
5508 }
5509 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-select") )
5510 {
5511 const char* pszSelect = papszArgv[++i];
5512 CSLDestroy(psOptions->papszSelFields);
5513 psOptions->papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,",
5514 FALSE, FALSE );
5515 }
5516 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-segmentize") )
5517 {
5518 psOptions->eGeomOp = GEOMOP_SEGMENTIZE;
5519 psOptions->dfGeomOpParam = CPLAtof(papszArgv[++i]);
5520 }
5521 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-simplify") )
5522 {
5523 psOptions->eGeomOp = GEOMOP_SIMPLIFY_PRESERVE_TOPOLOGY;
5524 psOptions->dfGeomOpParam = CPLAtof(papszArgv[++i]);
5525 }
5526 else if( EQUAL(papszArgv[i],"-makevalid") )
5527 {
5528 // Check that OGRGeometry::MakeValid() is available
5529 OGRGeometry* poInputGeom = nullptr;
5530 OGRGeometryFactory::createFromWkt(
5531 "POLYGON((0 0,1 1,1 0,0 1,0 0))", nullptr, &poInputGeom );
5532 CPLAssert(poInputGeom);
5533 OGRGeometry* poValidGeom = poInputGeom->MakeValid();
5534 delete poInputGeom;
5535 if( poValidGeom == nullptr )
5536 {
5537 CPLError(CE_Failure, CPLE_NotSupported,
5538 "-makevalid only supported for builds against GEOS 3.8 or later");
5539 GDALVectorTranslateOptionsFree(psOptions);
5540 return nullptr;
5541 }
5542 delete poValidGeom;
5543 psOptions->bMakeValid = true;
5544 }
5545 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-fieldTypeToString") )
5546 {
5547 CSLDestroy(psOptions->papszFieldTypesToString);
5548 psOptions->papszFieldTypesToString =
5549 CSLTokenizeStringComplex(papszArgv[++i], " ,",
5550 FALSE, FALSE );
5551 char** iter = psOptions->papszFieldTypesToString;
5552 while(*iter)
5553 {
5554 if (IsFieldType(*iter))
5555 {
5556 /* Do nothing */
5557 }
5558 else if (EQUAL(*iter, "All"))
5559 {
5560 CSLDestroy(psOptions->papszFieldTypesToString);
5561 psOptions->papszFieldTypesToString = nullptr;
5562 psOptions->papszFieldTypesToString = CSLAddString(psOptions->papszFieldTypesToString, "All");
5563 break;
5564 }
5565 else
5566 {
5567 CPLError(CE_Failure, CPLE_IllegalArg,
5568 "Unhandled type for fieldTypeToString option : %s",
5569 *iter);
5570 GDALVectorTranslateOptionsFree(psOptions);
5571 return nullptr;
5572 }
5573 iter ++;
5574 }
5575 }
5576 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-mapFieldType") )
5577 {
5578 CSLDestroy(psOptions->papszMapFieldType);
5579 psOptions->papszMapFieldType =
5580 CSLTokenizeStringComplex(papszArgv[++i], " ,",
5581 FALSE, FALSE );
5582 char** iter = psOptions->papszMapFieldType;
5583 while(*iter)
5584 {
5585 char* pszKey = nullptr;
5586 const char* pszValue = CPLParseNameValue(*iter, &pszKey);
5587 if( pszKey && pszValue)
5588 {
5589 if( !((IsFieldType(pszKey) || EQUAL(pszKey, "All")) && IsFieldType(pszValue)) )
5590 {
5591 CPLError(CE_Failure, CPLE_IllegalArg,
5592 "Invalid value for -mapFieldType : %s",
5593 *iter);
5594 CPLFree(pszKey);
5595 GDALVectorTranslateOptionsFree(psOptions);
5596 return nullptr;
5597 }
5598 }
5599 CPLFree(pszKey);
5600 iter ++;
5601 }
5602 }
5603 else if( EQUAL(papszArgv[i],"-unsetFieldWidth") )
5604 {
5605 psOptions->bUnsetFieldWidth = true;
5606 }
5607 else if( EQUAL(papszArgv[i],"-progress") )
5608 {
5609 psOptions->bDisplayProgress = true;
5610 }
5611 else if( EQUAL(papszArgv[i],"-wrapdateline") )
5612 {
5613 psOptions->bWrapDateline = true;
5614 }
5615 else if( i < nArgc-1 && EQUAL(papszArgv[i],"-datelineoffset") )
5616 {
5617 psOptions->dfDateLineOffset = CPLAtof(papszArgv[++i]);
5618 }
5619 else if( EQUAL(papszArgv[i],"-clipsrc") )
5620 {
5621 if (i + 1 >= nArgc)
5622 {
5623 CPLError(CE_Failure, CPLE_IllegalArg, "%s option requires 1 or 4 arguments", papszArgv[i]);
5624 GDALVectorTranslateOptionsFree(psOptions);
5625 return nullptr;
5626 }
5627
5628 OGR_G_DestroyGeometry(psOptions->hClipSrc);
5629 psOptions->hClipSrc = nullptr;
5630 CPLFree(psOptions->pszClipSrcDS);
5631 psOptions->pszClipSrcDS = nullptr;
5632
5633 VSIStatBufL sStat;
5634 psOptions->bClipSrc = true;
5635 if ( IsNumber(papszArgv[i+1])
5636 && papszArgv[i+2] != nullptr
5637 && papszArgv[i+3] != nullptr
5638 && papszArgv[i+4] != nullptr)
5639 {
5640 OGRLinearRing oRing;
5641
5642 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5643 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
5644 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
5645 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
5646 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5647
5648 OGRPolygon* poPoly = new OGRPolygon();
5649 psOptions->hClipSrc = reinterpret_cast<OGRGeometryH>(poPoly);
5650 poPoly->addRing( &oRing );
5651 i += 4;
5652 }
5653 else if ((STARTS_WITH_CI(papszArgv[i+1], "POLYGON") ||
5654 STARTS_WITH_CI(papszArgv[i+1], "MULTIPOLYGON")) &&
5655 VSIStatL(papszArgv[i+1], &sStat) != 0)
5656 {
5657 OGRGeometryFactory::createFromWkt(papszArgv[i+1], nullptr,
5658 reinterpret_cast<OGRGeometry **>(&psOptions->hClipSrc));
5659 if (psOptions->hClipSrc == nullptr)
5660 {
5661 CPLError(CE_Failure, CPLE_IllegalArg,
5662 "Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
5663 GDALVectorTranslateOptionsFree(psOptions);
5664 return nullptr;
5665 }
5666 i ++;
5667 }
5668 else if (EQUAL(papszArgv[i+1], "spat_extent") )
5669 {
5670 i ++;
5671 }
5672 else
5673 {
5674 psOptions->pszClipSrcDS = CPLStrdup(papszArgv[i+1]);
5675 i ++;
5676 }
5677 }
5678 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipsrcsql") )
5679 {
5680 CPLFree(psOptions->pszClipSrcSQL);
5681 psOptions->pszClipSrcSQL = CPLStrdup(papszArgv[i+1]);
5682 i ++;
5683 }
5684 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipsrclayer") )
5685 {
5686 CPLFree(psOptions->pszClipSrcLayer);
5687 psOptions->pszClipSrcLayer = CPLStrdup(papszArgv[i+1]);
5688 i ++;
5689 }
5690 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipsrcwhere") )
5691 {
5692 CPLFree(psOptions->pszClipSrcWhere);
5693 psOptions->pszClipSrcWhere = CPLStrdup(papszArgv[i+1]);
5694 i ++;
5695 }
5696 else if( EQUAL(papszArgv[i],"-clipdst") )
5697 {
5698 if (i + 1 >= nArgc)
5699 {
5700 CPLError(CE_Failure, CPLE_IllegalArg, "%s option requires 1 or 4 arguments", papszArgv[i]);
5701 GDALVectorTranslateOptionsFree(psOptions);
5702 return nullptr;
5703 }
5704
5705 OGR_G_DestroyGeometry(psOptions->hClipDst);
5706 psOptions->hClipDst = nullptr;
5707 CPLFree(psOptions->pszClipDstDS);
5708 psOptions->pszClipDstDS = nullptr;
5709
5710 VSIStatBufL sStat;
5711 if ( IsNumber(papszArgv[i+1])
5712 && papszArgv[i+2] != nullptr
5713 && papszArgv[i+3] != nullptr
5714 && papszArgv[i+4] != nullptr)
5715 {
5716 OGRLinearRing oRing;
5717
5718 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5719 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+4]) );
5720 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+4]) );
5721 oRing.addPoint( CPLAtof(papszArgv[i+3]), CPLAtof(papszArgv[i+2]) );
5722 oRing.addPoint( CPLAtof(papszArgv[i+1]), CPLAtof(papszArgv[i+2]) );
5723
5724 OGRPolygon* poPoly = new OGRPolygon();
5725 psOptions->hClipDst = reinterpret_cast<OGRGeometryH>(poPoly);
5726 poPoly->addRing( &oRing );
5727 i += 4;
5728 }
5729 else if ((STARTS_WITH_CI(papszArgv[i+1], "POLYGON") ||
5730 STARTS_WITH_CI(papszArgv[i+1], "MULTIPOLYGON")) &&
5731 VSIStatL(papszArgv[i+1], &sStat) != 0)
5732 {
5733 OGRGeometryFactory::createFromWkt(papszArgv[i+1],
5734 nullptr, reinterpret_cast<OGRGeometry **>(&psOptions->hClipDst));
5735 if (psOptions->hClipDst == nullptr)
5736 {
5737 CPLError(CE_Failure, CPLE_IllegalArg,
5738 "Invalid geometry. Must be a valid POLYGON or MULTIPOLYGON WKT");
5739 GDALVectorTranslateOptionsFree(psOptions);
5740 return nullptr;
5741 }
5742 i ++;
5743 }
5744 else
5745 {
5746 psOptions->pszClipDstDS = CPLStrdup(papszArgv[i+1]);
5747 i ++;
5748 }
5749 }
5750 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipdstsql") )
5751 {
5752 CPLFree(psOptions->pszClipDstSQL);
5753 psOptions->pszClipDstSQL = CPLStrdup(papszArgv[i+1]);
5754 i ++;
5755 }
5756 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipdstlayer") )
5757 {
5758 CPLFree(psOptions->pszClipDstLayer);
5759 psOptions->pszClipDstLayer = CPLStrdup(papszArgv[i+1]);
5760 i ++;
5761 }
5762 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-clipdstwhere") )
5763 {
5764 CPLFree(psOptions->pszClipDstWhere);
5765 psOptions->pszClipDstWhere = CPLStrdup(papszArgv[i+1]);
5766 i ++;
5767 }
5768 else if( EQUAL(papszArgv[i],"-splitlistfields") )
5769 {
5770 psOptions->bSplitListFields = true;
5771 }
5772 else if ( i+1 < nArgc && EQUAL(papszArgv[i],"-maxsubfields") )
5773 {
5774 if (IsNumber(papszArgv[i+1]))
5775 {
5776 int nTemp = atoi(papszArgv[i+1]);
5777 if (nTemp > 0)
5778 {
5779 psOptions->nMaxSplitListSubFields = nTemp;
5780 i ++;
5781 }
5782 }
5783 }
5784 else if( EQUAL(papszArgv[i],"-explodecollections") )
5785 {
5786 psOptions->bExplodeCollections = true;
5787 }
5788 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-zfield") )
5789 {
5790 CPLFree(psOptions->pszZField);
5791 psOptions->pszZField = CPLStrdup(papszArgv[i+1]);
5792 i ++;
5793 }
5794 else if( i+4 < nArgc && EQUAL(papszArgv[i],"-gcp") )
5795 {
5796 char* endptr = nullptr;
5797 /* -gcp pixel line easting northing [elev] */
5798
5799 psOptions->nGCPCount++;
5800 psOptions->pasGCPs = static_cast<GDAL_GCP *>(
5801 CPLRealloc(psOptions->pasGCPs,
5802 sizeof(GDAL_GCP) * psOptions->nGCPCount));
5803 GDALInitGCPs( 1, psOptions->pasGCPs + psOptions->nGCPCount - 1 );
5804
5805 psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPPixel = CPLAtof(papszArgv[++i]);
5806 psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPLine = CPLAtof(papszArgv[++i]);
5807 psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPX = CPLAtof(papszArgv[++i]);
5808 psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPY = CPLAtof(papszArgv[++i]);
5809 if( papszArgv[i+1] != nullptr
5810 && (CPLStrtod(papszArgv[i+1], &endptr) != 0.0 || papszArgv[i+1][0] == '0') )
5811 {
5812 /* Check that last argument is really a number and not a filename */
5813 /* looking like a number (see ticket #863) */
5814 if (endptr && *endptr == 0)
5815 psOptions->pasGCPs[psOptions->nGCPCount-1].dfGCPZ = CPLAtof(papszArgv[++i]);
5816 }
5817
5818 /* should set id and info? */
5819 }
5820 else if( EQUAL(papszArgv[i],"-tps") )
5821 {
5822 psOptions->nTransformOrder = -1;
5823 }
5824 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-order") )
5825 {
5826 psOptions->nTransformOrder = atoi( papszArgv[++i] );
5827 }
5828 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-fieldmap") )
5829 {
5830 CSLDestroy(psOptions->papszFieldMap);
5831 psOptions->papszFieldMap = CSLTokenizeStringComplex(papszArgv[++i], ",",
5832 FALSE, FALSE );
5833 }
5834 else if( EQUAL(papszArgv[i],"-emptyStrAsNull") )
5835 {
5836 psOptions->bEmptyStrAsNull = true;
5837 }
5838 else if( EQUAL(papszArgv[i],"-forceNullable") )
5839 {
5840 psOptions->bForceNullable = true;
5841 }
5842 else if( EQUAL(papszArgv[i],"-resolveDomains") )
5843 {
5844 psOptions->bResolveDomains = true;
5845 }
5846 else if( EQUAL(papszArgv[i],"-unsetDefault") )
5847 {
5848 psOptions->bUnsetDefault = true;
5849 }
5850 else if( EQUAL(papszArgv[i],"-unsetFid") )
5851 {
5852 psOptions->bUnsetFid = true;
5853 }
5854 else if( EQUAL(papszArgv[i],"-nomd") )
5855 {
5856 psOptions->bCopyMD = false;
5857 }
5858 else if( EQUAL(papszArgv[i],"-noNativeData") )
5859 {
5860 psOptions->bNativeData = false;
5861 }
5862 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-mo") )
5863 {
5864 psOptions->papszMetadataOptions = CSLAddString( psOptions->papszMetadataOptions,
5865 papszArgv[++i] );
5866 }
5867 else if( i+1 < nArgc && EQUAL(papszArgv[i],"-limit") )
5868 {
5869 psOptions->nLimit = CPLAtoGIntBig( papszArgv[++i] );
5870 }
5871 else if( papszArgv[i][0] == '-' )
5872 {
5873 CPLError(CE_Failure, CPLE_NotSupported,
5874 "Unknown option name '%s'", papszArgv[i]);
5875 GDALVectorTranslateOptionsFree(psOptions);
5876 return nullptr;
5877 }
5878 else if( psOptionsForBinary && psOptionsForBinary->pszDestDataSource == nullptr )
5879 psOptionsForBinary->pszDestDataSource = CPLStrdup(papszArgv[i]);
5880 else if( psOptionsForBinary && psOptionsForBinary->pszDataSource == nullptr )
5881 psOptionsForBinary->pszDataSource = CPLStrdup(papszArgv[i]);
5882 else
5883 psOptions->papszLayers = CSLAddString( psOptions->papszLayers, papszArgv[i] );
5884 }
5885
5886 if( psOptionsForBinary )
5887 {
5888 psOptionsForBinary->eAccessMode = psOptions->eAccessMode;
5889 if( psOptions->pszFormat )
5890 psOptionsForBinary->pszFormat = CPLStrdup( psOptions->pszFormat );
5891
5892 if( !(CPLTestBool(CSLFetchNameValueDef(
5893 psOptionsForBinary->papszOpenOptions, "NATIVE_DATA",
5894 CSLFetchNameValueDef(
5895 psOptionsForBinary->papszOpenOptions, "@NATIVE_DATA", "TRUE")))) )
5896 {
5897 psOptions->bNativeData = false;
5898 }
5899
5900 if( psOptions->bNativeData &&
5901 CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
5902 "NATIVE_DATA") == nullptr &&
5903 CSLFetchNameValue(psOptionsForBinary->papszOpenOptions,
5904 "@NATIVE_DATA") == nullptr )
5905 {
5906 psOptionsForBinary->papszOpenOptions = CSLAddString(
5907 psOptionsForBinary->papszOpenOptions, "@NATIVE_DATA=YES" );
5908 }
5909 }
5910
5911 return psOptions;
5912 }
5913
5914 /************************************************************************/
5915 /* GDALVectorTranslateOptionsFree() */
5916 /************************************************************************/
5917
5918 /**
5919 * Frees the GDALVectorTranslateOptions struct.
5920 *
5921 * @param psOptions the options struct for GDALVectorTranslate().
5922 * @since GDAL 2.1
5923 */
5924
GDALVectorTranslateOptionsFree(GDALVectorTranslateOptions * psOptions)5925 void GDALVectorTranslateOptionsFree( GDALVectorTranslateOptions *psOptions )
5926 {
5927 if( psOptions == nullptr )
5928 return;
5929
5930 CPLFree( psOptions->pszFormat );
5931 CPLFree( psOptions->pszOutputSRSDef);
5932 CPLFree( psOptions->pszSourceSRSDef);
5933 CPLFree( psOptions->pszCTPipeline );
5934 CPLFree( psOptions->pszNewLayerName);
5935 CPLFree( psOptions->pszWHERE );
5936 CPLFree( psOptions->pszGeomField );
5937 CPLFree( psOptions->pszSQLStatement );
5938 CPLFree( psOptions->pszDialect );
5939 CPLFree( psOptions->pszClipSrcDS );
5940 CPLFree( psOptions->pszClipSrcSQL );
5941 CPLFree( psOptions->pszClipSrcLayer );
5942 CPLFree( psOptions->pszClipSrcWhere );
5943 CPLFree( psOptions->pszClipDstDS );
5944 CPLFree( psOptions->pszClipDstSQL );
5945 CPLFree( psOptions->pszClipDstLayer );
5946 CPLFree( psOptions->pszClipDstWhere );
5947 CPLFree( psOptions->pszZField );
5948 CPLFree( psOptions->pszSpatSRSDef );
5949 CSLDestroy(psOptions->papszSelFields);
5950 CSLDestroy( psOptions->papszFieldMap );
5951 CSLDestroy( psOptions->papszMapFieldType );
5952 CSLDestroy( psOptions->papszLayers );
5953 CSLDestroy( psOptions->papszDSCO );
5954 CSLDestroy( psOptions->papszLCO );
5955 CSLDestroy( psOptions->papszDestOpenOptions );
5956 CSLDestroy( psOptions->papszFieldTypesToString );
5957 CSLDestroy( psOptions->papszMetadataOptions );
5958
5959 if( psOptions->pasGCPs != nullptr )
5960 {
5961 GDALDeinitGCPs( psOptions->nGCPCount, psOptions->pasGCPs );
5962 CPLFree( psOptions->pasGCPs );
5963 }
5964
5965 if( psOptions->hClipSrc != nullptr )
5966 OGR_G_DestroyGeometry( psOptions->hClipSrc );
5967 if( psOptions->hClipDst != nullptr )
5968 OGR_G_DestroyGeometry( psOptions->hClipDst );
5969 if( psOptions->hSpatialFilter != nullptr )
5970 OGR_G_DestroyGeometry( psOptions->hSpatialFilter );
5971
5972 CPLFree(psOptions);
5973 }
5974
5975 /************************************************************************/
5976 /* GDALVectorTranslateOptionsSetProgress() */
5977 /************************************************************************/
5978
5979 /**
5980 * Set a progress function.
5981 *
5982 * @param psOptions the options struct for GDALVectorTranslate().
5983 * @param pfnProgress the progress callback.
5984 * @param pProgressData the user data for the progress callback.
5985 *
5986 * @since GDAL 2.1
5987 */
5988
GDALVectorTranslateOptionsSetProgress(GDALVectorTranslateOptions * psOptions,GDALProgressFunc pfnProgress,void * pProgressData)5989 void GDALVectorTranslateOptionsSetProgress( GDALVectorTranslateOptions *psOptions,
5990 GDALProgressFunc pfnProgress, void *pProgressData )
5991 {
5992 psOptions->pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
5993 psOptions->pProgressData = pProgressData;
5994 if( pfnProgress == GDALTermProgress )
5995 psOptions->bQuiet = false;
5996 }
5997