Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRUnionLayer class
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef DOXYGEN_SKIP
14 :
15 : #include "ogrunionlayer.h"
16 : #include "ogrwarpedlayer.h"
17 : #include "ogr_p.h"
18 :
19 : /************************************************************************/
20 : /* OGRUnionLayerGeomFieldDefn() */
21 : /************************************************************************/
22 :
23 21 : OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char *pszNameIn,
24 21 : OGRwkbGeometryType eType)
25 21 : : OGRGeomFieldDefn(pszNameIn, eType)
26 : {
27 21 : }
28 :
29 : /************************************************************************/
30 : /* OGRUnionLayerGeomFieldDefn() */
31 : /************************************************************************/
32 :
33 84 : OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
34 84 : const OGRGeomFieldDefn *poSrc)
35 84 : : OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType())
36 : {
37 84 : SetSpatialRef(poSrc->GetSpatialRef());
38 84 : }
39 :
40 : /************************************************************************/
41 : /* OGRUnionLayerGeomFieldDefn() */
42 : /************************************************************************/
43 :
44 31 : OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
45 31 : const OGRUnionLayerGeomFieldDefn *poSrc)
46 : : OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
47 31 : bGeomTypeSet(poSrc->bGeomTypeSet), bSRSSet(poSrc->bSRSSet)
48 : {
49 31 : SetSpatialRef(poSrc->GetSpatialRef());
50 31 : sStaticEnvelope = poSrc->sStaticEnvelope;
51 31 : }
52 :
53 : /************************************************************************/
54 : /* ~OGRUnionLayerGeomFieldDefn() */
55 : /************************************************************************/
56 :
57 272 : OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn()
58 : {
59 272 : }
60 :
61 : /************************************************************************/
62 : /* OGRUnionLayer() */
63 : /************************************************************************/
64 :
65 : // cppcheck-suppress uninitMemberVar
66 91 : OGRUnionLayer::OGRUnionLayer(const char *pszName, int nSrcLayersIn,
67 : OGRLayer **papoSrcLayersIn,
68 91 : int bTakeLayerOwnership)
69 : : osName(pszName), nSrcLayers(nSrcLayersIn), papoSrcLayers(papoSrcLayersIn),
70 : bHasLayerOwnership(bTakeLayerOwnership),
71 182 : pabModifiedLayers(static_cast<int *>(CPLCalloc(sizeof(int), nSrcLayers))),
72 91 : pabCheckIfAutoWrap(static_cast<int *>(CPLCalloc(sizeof(int), nSrcLayers)))
73 : {
74 91 : CPLAssert(nSrcLayersIn > 0);
75 :
76 91 : SetDescription(pszName);
77 91 : }
78 :
79 : /************************************************************************/
80 : /* ~OGRUnionLayer() */
81 : /************************************************************************/
82 :
83 182 : OGRUnionLayer::~OGRUnionLayer()
84 : {
85 91 : if (bHasLayerOwnership)
86 : {
87 266 : for (int i = 0; i < nSrcLayers; i++)
88 175 : delete papoSrcLayers[i];
89 : }
90 91 : CPLFree(papoSrcLayers);
91 :
92 123 : for (int i = 0; i < nFields; i++)
93 32 : delete papoFields[i];
94 91 : CPLFree(papoFields);
95 114 : for (int i = 0; i < nGeomFields; i++)
96 23 : delete papoGeomFields[i];
97 91 : CPLFree(papoGeomFields);
98 :
99 91 : CPLFree(pszAttributeFilter);
100 91 : CPLFree(panMap);
101 91 : CPLFree(pabModifiedLayers);
102 91 : CPLFree(pabCheckIfAutoWrap);
103 :
104 91 : if (poFeatureDefn)
105 75 : poFeatureDefn->Release();
106 91 : if (poGlobalSRS != nullptr)
107 26 : const_cast<OGRSpatialReference *>(poGlobalSRS)->Release();
108 182 : }
109 :
110 : /************************************************************************/
111 : /* SetFields() */
112 : /************************************************************************/
113 :
114 86 : void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
115 : int nFieldsIn, OGRFieldDefn **papoFieldsIn,
116 : int nGeomFieldsIn,
117 : OGRUnionLayerGeomFieldDefn **papoGeomFieldsIn)
118 : {
119 86 : CPLAssert(nFields == 0);
120 86 : CPLAssert(poFeatureDefn == nullptr);
121 :
122 86 : eFieldStrategy = eFieldStrategyIn;
123 86 : if (nFieldsIn)
124 : {
125 2 : nFields = nFieldsIn;
126 2 : papoFields = static_cast<OGRFieldDefn **>(
127 2 : CPLMalloc(nFields * sizeof(OGRFieldDefn *)));
128 34 : for (int i = 0; i < nFields; i++)
129 32 : papoFields[i] = new OGRFieldDefn(papoFieldsIn[i]);
130 : }
131 86 : nGeomFields = nGeomFieldsIn;
132 86 : if (nGeomFields > 0)
133 : {
134 17 : papoGeomFields = static_cast<OGRUnionLayerGeomFieldDefn **>(
135 17 : CPLMalloc(nGeomFields * sizeof(OGRUnionLayerGeomFieldDefn *)));
136 40 : for (int i = 0; i < nGeomFields; i++)
137 23 : papoGeomFields[i] =
138 23 : new OGRUnionLayerGeomFieldDefn(papoGeomFieldsIn[i]);
139 : }
140 86 : }
141 :
142 : /************************************************************************/
143 : /* SetSourceLayerFieldName() */
144 : /************************************************************************/
145 :
146 84 : void OGRUnionLayer::SetSourceLayerFieldName(const char *pszSourceLayerFieldName)
147 : {
148 84 : CPLAssert(poFeatureDefn == nullptr);
149 :
150 84 : CPLAssert(osSourceLayerFieldName.empty());
151 84 : if (pszSourceLayerFieldName != nullptr)
152 10 : osSourceLayerFieldName = pszSourceLayerFieldName;
153 84 : }
154 :
155 : /************************************************************************/
156 : /* SetPreserveSrcFID() */
157 : /************************************************************************/
158 :
159 84 : void OGRUnionLayer::SetPreserveSrcFID(int bPreserveSrcFIDIn)
160 : {
161 84 : CPLAssert(poFeatureDefn == nullptr);
162 :
163 84 : bPreserveSrcFID = bPreserveSrcFIDIn;
164 84 : }
165 :
166 : /************************************************************************/
167 : /* SetFeatureCount() */
168 : /************************************************************************/
169 :
170 9 : void OGRUnionLayer::SetFeatureCount(int nFeatureCountIn)
171 : {
172 9 : CPLAssert(poFeatureDefn == nullptr);
173 :
174 9 : nFeatureCount = nFeatureCountIn;
175 9 : }
176 :
177 : /************************************************************************/
178 : /* MergeFieldDefn() */
179 : /************************************************************************/
180 :
181 55 : static void MergeFieldDefn(OGRFieldDefn *poFieldDefn,
182 : const OGRFieldDefn *poSrcFieldDefn)
183 : {
184 55 : if (poFieldDefn->GetType() != poSrcFieldDefn->GetType())
185 : {
186 20 : if (poSrcFieldDefn->GetType() == OFTReal &&
187 0 : (poFieldDefn->GetType() == OFTInteger ||
188 0 : poFieldDefn->GetType() == OFTInteger64))
189 0 : poFieldDefn->SetType(OFTReal);
190 20 : if (poFieldDefn->GetType() == OFTReal &&
191 0 : (poSrcFieldDefn->GetType() == OFTInteger ||
192 0 : poSrcFieldDefn->GetType() == OFTInteger64))
193 0 : poFieldDefn->SetType(OFTReal);
194 36 : else if (poSrcFieldDefn->GetType() == OFTInteger64 &&
195 16 : poFieldDefn->GetType() == OFTInteger)
196 16 : poFieldDefn->SetType(OFTInteger64);
197 4 : else if (poFieldDefn->GetType() == OFTInteger64 &&
198 0 : poSrcFieldDefn->GetType() == OFTInteger)
199 0 : poFieldDefn->SetType(OFTInteger64);
200 : else
201 4 : poFieldDefn->SetType(OFTString);
202 : }
203 :
204 86 : if (poFieldDefn->GetWidth() != poSrcFieldDefn->GetWidth() ||
205 31 : poFieldDefn->GetPrecision() != poSrcFieldDefn->GetPrecision())
206 : {
207 24 : poFieldDefn->SetWidth(0);
208 24 : poFieldDefn->SetPrecision(0);
209 : }
210 55 : }
211 :
212 : /************************************************************************/
213 : /* GetLayerDefn() */
214 : /************************************************************************/
215 :
216 6776 : OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
217 : {
218 6776 : if (poFeatureDefn != nullptr)
219 6701 : return poFeatureDefn;
220 :
221 75 : poFeatureDefn = new OGRFeatureDefn(osName);
222 75 : poFeatureDefn->Reference();
223 75 : poFeatureDefn->SetGeomType(wkbNone);
224 :
225 75 : int iCompareFirstIndex = 0;
226 75 : if (!osSourceLayerFieldName.empty())
227 : {
228 6 : OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
229 6 : poFeatureDefn->AddFieldDefn(&oField);
230 6 : iCompareFirstIndex = 1;
231 : }
232 :
233 75 : if (eFieldStrategy == FIELD_SPECIFIED)
234 : {
235 4 : for (int i = 0; i < nFields; i++)
236 0 : poFeatureDefn->AddFieldDefn(papoFields[i]);
237 12 : for (int i = 0; i < nGeomFields; i++)
238 : {
239 8 : poFeatureDefn->AddGeomFieldDefn(
240 8 : std::make_unique<OGRUnionLayerGeomFieldDefn>(
241 8 : papoGeomFields[i]));
242 : OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
243 8 : cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
244 8 : poFeatureDefn->GetGeomFieldDefn(i));
245 :
246 8 : if (poGeomFieldDefn->bGeomTypeSet == FALSE ||
247 2 : poGeomFieldDefn->bSRSSet == FALSE)
248 : {
249 8 : for (int iLayer = 0; iLayer < nSrcLayers; iLayer++)
250 : {
251 : OGRFeatureDefn *poSrcFeatureDefn =
252 8 : papoSrcLayers[iLayer]->GetLayerDefn();
253 8 : int nIndex = poSrcFeatureDefn->GetGeomFieldIndex(
254 8 : poGeomFieldDefn->GetNameRef());
255 8 : if (nIndex >= 0)
256 : {
257 : OGRGeomFieldDefn *poSrcGeomFieldDefn =
258 8 : poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
259 8 : if (poGeomFieldDefn->bGeomTypeSet == FALSE)
260 : {
261 6 : poGeomFieldDefn->bGeomTypeSet = TRUE;
262 6 : poGeomFieldDefn->SetType(
263 : poSrcGeomFieldDefn->GetType());
264 : }
265 8 : if (poGeomFieldDefn->bSRSSet == FALSE)
266 : {
267 6 : poGeomFieldDefn->bSRSSet = TRUE;
268 6 : poGeomFieldDefn->SetSpatialRef(
269 6 : poSrcGeomFieldDefn->GetSpatialRef());
270 6 : if (i == 0 && poGlobalSRS == nullptr)
271 : {
272 4 : poGlobalSRS =
273 4 : poSrcGeomFieldDefn->GetSpatialRef();
274 4 : if (poGlobalSRS != nullptr)
275 : const_cast<OGRSpatialReference *>(
276 4 : poGlobalSRS)
277 4 : ->Reference();
278 : }
279 : }
280 8 : break;
281 : }
282 : }
283 : }
284 : }
285 : }
286 71 : else if (eFieldStrategy == FIELD_FROM_FIRST_LAYER)
287 : {
288 : const OGRFeatureDefn *poSrcFeatureDefn =
289 4 : papoSrcLayers[0]->GetLayerDefn();
290 4 : const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
291 46 : for (int i = 0; i < nSrcFieldCount; i++)
292 42 : poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
293 4 : for (int i = 0;
294 12 : nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
295 : i++)
296 : {
297 : const OGRGeomFieldDefn *poFldDefn =
298 8 : poSrcFeatureDefn->GetGeomFieldDefn(i);
299 8 : poFeatureDefn->AddGeomFieldDefn(
300 16 : std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
301 : }
302 : }
303 67 : else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS)
304 : {
305 60 : if (nGeomFields == 1)
306 : {
307 0 : poFeatureDefn->AddGeomFieldDefn(
308 0 : std::make_unique<OGRUnionLayerGeomFieldDefn>(
309 0 : papoGeomFields[0]));
310 : }
311 :
312 60 : int nDstFieldCount = 0;
313 120 : std::map<std::string, int> oMapDstFieldNameToIdx;
314 :
315 176 : for (int iLayer = 0; iLayer < nSrcLayers; iLayer++)
316 : {
317 : const OGRFeatureDefn *poSrcFeatureDefn =
318 116 : papoSrcLayers[iLayer]->GetLayerDefn();
319 :
320 : /* Add any field that is found in the source layers */
321 116 : const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
322 264 : for (int i = 0; i < nSrcFieldCount; i++)
323 : {
324 : const OGRFieldDefn *poSrcFieldDefn =
325 148 : poSrcFeatureDefn->GetFieldDefn(i);
326 : const auto oIter =
327 148 : oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
328 : const int nIndex =
329 148 : oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
330 148 : if (nIndex < 0)
331 : {
332 106 : oMapDstFieldNameToIdx[poSrcFieldDefn->GetNameRef()] =
333 : nDstFieldCount;
334 106 : nDstFieldCount++;
335 106 : poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
336 : }
337 : else
338 : {
339 : OGRFieldDefn *poFieldDefn =
340 42 : poFeatureDefn->GetFieldDefn(nIndex);
341 42 : MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
342 : }
343 : }
344 :
345 229 : for (int i = 0;
346 229 : nGeomFields != -1 && i < poSrcFeatureDefn->GetGeomFieldCount();
347 : i++)
348 : {
349 : const OGRGeomFieldDefn *poSrcFieldDefn =
350 113 : poSrcFeatureDefn->GetGeomFieldDefn(i);
351 113 : int nIndex = poFeatureDefn->GetGeomFieldIndex(
352 113 : poSrcFieldDefn->GetNameRef());
353 113 : if (nIndex < 0)
354 : {
355 63 : poFeatureDefn->AddGeomFieldDefn(
356 63 : std::make_unique<OGRUnionLayerGeomFieldDefn>(
357 63 : poSrcFieldDefn));
358 63 : if (poFeatureDefn->GetGeomFieldCount() == 1 &&
359 63 : nGeomFields == 0 && GetSpatialRef() != nullptr)
360 : {
361 : OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
362 19 : cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
363 19 : poFeatureDefn->GetGeomFieldDefn(0));
364 19 : poGeomFieldDefn->bSRSSet = TRUE;
365 19 : poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
366 : }
367 : }
368 : else
369 : {
370 50 : if (nIndex == 0 && nGeomFields == 1)
371 : {
372 : OGRUnionLayerGeomFieldDefn *poGeomFieldDefn =
373 0 : cpl::down_cast<OGRUnionLayerGeomFieldDefn *>(
374 0 : poFeatureDefn->GetGeomFieldDefn(0));
375 0 : if (poGeomFieldDefn->bGeomTypeSet == FALSE)
376 : {
377 0 : poGeomFieldDefn->bGeomTypeSet = TRUE;
378 0 : poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
379 : }
380 0 : if (poGeomFieldDefn->bSRSSet == FALSE)
381 : {
382 0 : poGeomFieldDefn->bSRSSet = TRUE;
383 0 : poGeomFieldDefn->SetSpatialRef(
384 0 : poSrcFieldDefn->GetSpatialRef());
385 : }
386 : }
387 : /* TODO: merge type, SRS, extent ? */
388 : }
389 : }
390 : }
391 : }
392 7 : else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS)
393 : {
394 7 : OGRFeatureDefn *poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
395 27 : for (int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
396 20 : poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
397 18 : for (int i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
398 : {
399 11 : OGRGeomFieldDefn *poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
400 11 : poFeatureDefn->AddGeomFieldDefn(
401 22 : std::make_unique<OGRUnionLayerGeomFieldDefn>(poFldDefn));
402 : }
403 :
404 : /* Remove any field that is not found in the source layers */
405 14 : for (int iLayer = 1; iLayer < nSrcLayers; iLayer++)
406 : {
407 : OGRFeatureDefn *l_poSrcFeatureDefn =
408 7 : papoSrcLayers[iLayer]->GetLayerDefn();
409 27 : for (int i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();
410 : // No increment.
411 : )
412 : {
413 20 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
414 20 : int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
415 20 : poFieldDefn->GetNameRef());
416 20 : if (nSrcIndex < 0)
417 : {
418 7 : poFeatureDefn->DeleteFieldDefn(i);
419 : }
420 : else
421 : {
422 : OGRFieldDefn *poSrcFieldDefn =
423 13 : l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
424 13 : MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
425 :
426 13 : i++;
427 : }
428 : }
429 18 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount();
430 : // No increment.
431 : )
432 : {
433 : OGRGeomFieldDefn *poFieldDefn =
434 11 : poFeatureDefn->GetGeomFieldDefn(i);
435 11 : int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
436 11 : poFieldDefn->GetNameRef());
437 11 : if (nSrcIndex < 0)
438 : {
439 2 : poFeatureDefn->DeleteGeomFieldDefn(i);
440 : }
441 : else
442 : {
443 : /* TODO: merge type, SRS, extent ? */
444 :
445 9 : i++;
446 : }
447 : }
448 : }
449 : }
450 :
451 75 : return poFeatureDefn;
452 : }
453 :
454 : /************************************************************************/
455 : /* GetGeomType() */
456 : /************************************************************************/
457 :
458 10 : OGRwkbGeometryType OGRUnionLayer::GetGeomType()
459 : {
460 10 : if (nGeomFields < 0)
461 1 : return wkbNone;
462 9 : if (nGeomFields >= 1 && papoGeomFields[0]->bGeomTypeSet)
463 : {
464 2 : return papoGeomFields[0]->GetType();
465 : }
466 :
467 7 : return OGRLayer::GetGeomType();
468 : }
469 :
470 : /************************************************************************/
471 : /* SetSpatialFilterToSourceLayer() */
472 : /************************************************************************/
473 :
474 1637 : void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer *poSrcLayer)
475 : {
476 3274 : if (m_iGeomFieldFilter >= 0 &&
477 1637 : m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount())
478 : {
479 3024 : int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
480 1512 : GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
481 1512 : if (iSrcGeomField >= 0)
482 : {
483 1511 : poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
484 : }
485 : else
486 : {
487 1 : poSrcLayer->SetSpatialFilter(nullptr);
488 : }
489 : }
490 : else
491 : {
492 125 : poSrcLayer->SetSpatialFilter(nullptr);
493 : }
494 1637 : }
495 :
496 : /************************************************************************/
497 : /* ConfigureActiveLayer() */
498 : /************************************************************************/
499 :
500 1119 : void OGRUnionLayer::ConfigureActiveLayer()
501 : {
502 1119 : AutoWarpLayerIfNecessary(iCurLayer);
503 1119 : ApplyAttributeFilterToSrcLayer(iCurLayer);
504 1119 : SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
505 1119 : papoSrcLayers[iCurLayer]->ResetReading();
506 :
507 : /* Establish map */
508 1119 : GetLayerDefn();
509 : const OGRFeatureDefn *poSrcFeatureDefn =
510 1119 : papoSrcLayers[iCurLayer]->GetLayerDefn();
511 1119 : const int nSrcFieldCount = poSrcFeatureDefn->GetFieldCount();
512 1119 : const int nDstFieldCount = poFeatureDefn->GetFieldCount();
513 :
514 2238 : std::map<std::string, int> oMapDstFieldNameToIdx;
515 4954 : for (int i = 0; i < nDstFieldCount; i++)
516 : {
517 3835 : const OGRFieldDefn *poDstFieldDefn = poFeatureDefn->GetFieldDefn(i);
518 3835 : oMapDstFieldNameToIdx[poDstFieldDefn->GetNameRef()] = i;
519 : }
520 :
521 1119 : CPLFree(panMap);
522 1119 : panMap = static_cast<int *>(CPLMalloc(nSrcFieldCount * sizeof(int)));
523 5859 : for (int i = 0; i < nSrcFieldCount; i++)
524 : {
525 4740 : const OGRFieldDefn *poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
526 4740 : if (m_aosIgnoredFields.FindString(poSrcFieldDefn->GetNameRef()) == -1)
527 : {
528 : const auto oIter =
529 4730 : oMapDstFieldNameToIdx.find(poSrcFieldDefn->GetNameRef());
530 4730 : panMap[i] =
531 4730 : oIter == oMapDstFieldNameToIdx.end() ? -1 : oIter->second;
532 : }
533 : else
534 : {
535 10 : panMap[i] = -1;
536 : }
537 : }
538 :
539 1119 : if (papoSrcLayers[iCurLayer]->TestCapability(OLCIgnoreFields))
540 : {
541 2218 : CPLStringList aosFieldSrc;
542 1135 : for (const char *pszFieldName : cpl::Iterate(m_aosIgnoredFields))
543 : {
544 64 : if (EQUAL(pszFieldName, "OGR_GEOMETRY") ||
545 12 : EQUAL(pszFieldName, "OGR_STYLE") ||
546 40 : poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
547 2 : poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0)
548 : {
549 24 : aosFieldSrc.AddString(pszFieldName);
550 : }
551 : }
552 :
553 2218 : std::map<std::string, int> oMapSrcFieldNameToIdx;
554 5799 : for (int i = 0; i < nSrcFieldCount; i++)
555 : {
556 : const OGRFieldDefn *poSrcFieldDefn =
557 4690 : poSrcFeatureDefn->GetFieldDefn(i);
558 4690 : oMapSrcFieldNameToIdx[poSrcFieldDefn->GetNameRef()] = i;
559 : }
560 :
561 : /* Attribute fields */
562 2218 : std::vector<bool> abSrcFieldsUsed(nSrcFieldCount);
563 4872 : for (int iField = 0; iField < nDstFieldCount; iField++)
564 : {
565 : const OGRFieldDefn *poFieldDefn =
566 3763 : poFeatureDefn->GetFieldDefn(iField);
567 : const auto oIter =
568 3763 : oMapSrcFieldNameToIdx.find(poFieldDefn->GetNameRef());
569 : const int iSrcField =
570 3763 : oIter == oMapSrcFieldNameToIdx.end() ? -1 : oIter->second;
571 3763 : if (iSrcField >= 0)
572 3201 : abSrcFieldsUsed[iSrcField] = true;
573 : }
574 5799 : for (int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++)
575 : {
576 4690 : if (!abSrcFieldsUsed[iSrcField])
577 : {
578 : const OGRFieldDefn *poSrcDefn =
579 1489 : poSrcFeatureDefn->GetFieldDefn(iSrcField);
580 1489 : aosFieldSrc.AddString(poSrcDefn->GetNameRef());
581 : }
582 : }
583 :
584 : /* geometry fields now */
585 1109 : abSrcFieldsUsed.clear();
586 1109 : abSrcFieldsUsed.resize(poSrcFeatureDefn->GetGeomFieldCount());
587 3371 : for (int iField = 0; iField < poFeatureDefn->GetGeomFieldCount();
588 : iField++)
589 : {
590 : const OGRGeomFieldDefn *poFieldDefn =
591 2262 : poFeatureDefn->GetGeomFieldDefn(iField);
592 : const int iSrcField =
593 2262 : poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
594 2262 : if (iSrcField >= 0)
595 2063 : abSrcFieldsUsed[iSrcField] = true;
596 : }
597 3862 : for (int iSrcField = 0;
598 3862 : iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField++)
599 : {
600 2753 : if (!abSrcFieldsUsed[iSrcField])
601 : {
602 : const OGRGeomFieldDefn *poSrcDefn =
603 690 : poSrcFeatureDefn->GetGeomFieldDefn(iSrcField);
604 690 : aosFieldSrc.AddString(poSrcDefn->GetNameRef());
605 : }
606 : }
607 :
608 1109 : papoSrcLayers[iCurLayer]->SetIgnoredFields(aosFieldSrc.List());
609 : }
610 1119 : }
611 :
612 : /************************************************************************/
613 : /* ResetReading() */
614 : /************************************************************************/
615 :
616 892 : void OGRUnionLayer::ResetReading()
617 : {
618 892 : iCurLayer = 0;
619 892 : ConfigureActiveLayer();
620 892 : nNextFID = 0;
621 892 : }
622 :
623 : /************************************************************************/
624 : /* AutoWarpLayerIfNecessary() */
625 : /************************************************************************/
626 :
627 1468 : void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
628 : {
629 1468 : if (!pabCheckIfAutoWrap[iLayer])
630 : {
631 71 : pabCheckIfAutoWrap[iLayer] = TRUE;
632 :
633 167 : for (int i = 0; i < GetLayerDefn()->GetGeomFieldCount(); i++)
634 : {
635 : const OGRSpatialReference *poSRS =
636 96 : GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef();
637 :
638 : OGRFeatureDefn *poSrcFeatureDefn =
639 96 : papoSrcLayers[iLayer]->GetLayerDefn();
640 96 : int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
641 96 : GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef());
642 96 : if (iSrcGeomField >= 0)
643 : {
644 : const OGRSpatialReference *poSRS2 =
645 87 : poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)
646 87 : ->GetSpatialRef();
647 :
648 87 : if ((poSRS == nullptr && poSRS2 != nullptr) ||
649 84 : (poSRS != nullptr && poSRS2 == nullptr))
650 : {
651 0 : CPLError(CE_Warning, CPLE_AppDefined,
652 : "SRS of geometry field '%s' layer %s not "
653 : "consistent with UnionLayer SRS",
654 0 : GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
655 0 : papoSrcLayers[iLayer]->GetName());
656 : }
657 84 : else if (poSRS != nullptr && poSRS2 != nullptr &&
658 171 : poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
659 : {
660 3 : CPLDebug("VRT",
661 : "SRS of geometry field '%s' layer %s not "
662 : "consistent with UnionLayer SRS. "
663 : "Trying auto warping",
664 3 : GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
665 3 : papoSrcLayers[iLayer]->GetName());
666 : OGRCoordinateTransformation *poCT =
667 3 : OGRCreateCoordinateTransformation(poSRS2, poSRS);
668 : OGRCoordinateTransformation *poReversedCT =
669 : (poCT != nullptr)
670 3 : ? OGRCreateCoordinateTransformation(poSRS, poSRS2)
671 3 : : nullptr;
672 3 : if (poReversedCT != nullptr)
673 3 : papoSrcLayers[iLayer] = new OGRWarpedLayer(
674 3 : papoSrcLayers[iLayer], iSrcGeomField, TRUE, poCT,
675 3 : poReversedCT);
676 : else
677 : {
678 0 : CPLError(CE_Warning, CPLE_AppDefined,
679 : "AutoWarpLayerIfNecessary failed to create "
680 : "poCT or poReversedCT.");
681 0 : if (poCT != nullptr)
682 0 : delete poCT;
683 : }
684 : }
685 : }
686 : }
687 : }
688 1468 : }
689 :
690 : /************************************************************************/
691 : /* GetNextFeature() */
692 : /************************************************************************/
693 :
694 2293 : OGRFeature *OGRUnionLayer::GetNextFeature()
695 : {
696 2293 : if (poFeatureDefn == nullptr)
697 3 : GetLayerDefn();
698 2293 : if (iCurLayer < 0)
699 10 : ResetReading();
700 :
701 2293 : if (iCurLayer == nSrcLayers)
702 8 : return nullptr;
703 :
704 : while (true)
705 : {
706 3015 : OGRFeature *poSrcFeature = papoSrcLayers[iCurLayer]->GetNextFeature();
707 3015 : if (poSrcFeature == nullptr)
708 : {
709 451 : iCurLayer++;
710 451 : if (iCurLayer < nSrcLayers)
711 : {
712 227 : ConfigureActiveLayer();
713 227 : continue;
714 : }
715 : else
716 224 : break;
717 : }
718 :
719 2564 : OGRFeature *poFeature = TranslateFromSrcLayer(poSrcFeature);
720 2564 : delete poSrcFeature;
721 :
722 5396 : if ((m_poFilterGeom == nullptr ||
723 5128 : FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter))) &&
724 2564 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
725 : {
726 2061 : return poFeature;
727 : }
728 :
729 503 : delete poFeature;
730 730 : }
731 224 : return nullptr;
732 : }
733 :
734 : /************************************************************************/
735 : /* GetFeature() */
736 : /************************************************************************/
737 :
738 48 : OGRFeature *OGRUnionLayer::GetFeature(GIntBig nFeatureId)
739 : {
740 48 : OGRFeature *poFeature = nullptr;
741 :
742 48 : if (!bPreserveSrcFID)
743 : {
744 48 : poFeature = OGRLayer::GetFeature(nFeatureId);
745 : }
746 : else
747 : {
748 0 : int iGeomFieldFilterSave = m_iGeomFieldFilter;
749 0 : OGRGeometry *poGeomSave = m_poFilterGeom;
750 0 : m_poFilterGeom = nullptr;
751 0 : SetSpatialFilter(nullptr);
752 :
753 0 : for (int i = 0; i < nSrcLayers; i++)
754 : {
755 0 : iCurLayer = i;
756 0 : ConfigureActiveLayer();
757 :
758 0 : OGRFeature *poSrcFeature = papoSrcLayers[i]->GetFeature(nFeatureId);
759 0 : if (poSrcFeature != nullptr)
760 : {
761 0 : poFeature = TranslateFromSrcLayer(poSrcFeature);
762 0 : delete poSrcFeature;
763 :
764 0 : break;
765 : }
766 : }
767 :
768 0 : SetSpatialFilter(iGeomFieldFilterSave, poGeomSave);
769 0 : delete poGeomSave;
770 :
771 0 : ResetReading();
772 : }
773 :
774 48 : return poFeature;
775 : }
776 :
777 : /************************************************************************/
778 : /* ICreateFeature() */
779 : /************************************************************************/
780 :
781 5 : OGRErr OGRUnionLayer::ICreateFeature(OGRFeature *poFeature)
782 : {
783 5 : if (osSourceLayerFieldName.empty())
784 : {
785 1 : CPLError(CE_Failure, CPLE_NotSupported,
786 : "CreateFeature() not supported when SourceLayerFieldName is "
787 : "not set");
788 1 : return OGRERR_FAILURE;
789 : }
790 :
791 4 : if (poFeature->GetFID() != OGRNullFID)
792 : {
793 1 : CPLError(CE_Failure, CPLE_NotSupported,
794 : "CreateFeature() not supported when FID is set");
795 1 : return OGRERR_FAILURE;
796 : }
797 :
798 3 : if (!poFeature->IsFieldSetAndNotNull(0))
799 : {
800 1 : CPLError(CE_Failure, CPLE_NotSupported,
801 : "CreateFeature() not supported when '%s' field is not set",
802 : osSourceLayerFieldName.c_str());
803 1 : return OGRERR_FAILURE;
804 : }
805 :
806 2 : const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
807 5 : for (int i = 0; i < nSrcLayers; i++)
808 : {
809 4 : if (strcmp(pszSrcLayerName, papoSrcLayers[i]->GetName()) == 0)
810 : {
811 1 : pabModifiedLayers[i] = TRUE;
812 :
813 : OGRFeature *poSrcFeature =
814 1 : new OGRFeature(papoSrcLayers[i]->GetLayerDefn());
815 1 : poSrcFeature->SetFrom(poFeature, TRUE);
816 1 : OGRErr eErr = papoSrcLayers[i]->CreateFeature(poSrcFeature);
817 1 : if (eErr == OGRERR_NONE)
818 1 : poFeature->SetFID(poSrcFeature->GetFID());
819 1 : delete poSrcFeature;
820 1 : return eErr;
821 : }
822 : }
823 :
824 1 : CPLError(CE_Failure, CPLE_NotSupported,
825 : "CreateFeature() not supported : '%s' source layer does not exist",
826 : pszSrcLayerName);
827 1 : return OGRERR_FAILURE;
828 : }
829 :
830 : /************************************************************************/
831 : /* ISetFeature() */
832 : /************************************************************************/
833 :
834 13 : OGRErr OGRUnionLayer::ISetFeature(OGRFeature *poFeature)
835 : {
836 13 : if (!bPreserveSrcFID)
837 : {
838 9 : CPLError(CE_Failure, CPLE_NotSupported,
839 : "SetFeature() not supported when PreserveSrcFID is OFF");
840 9 : return OGRERR_FAILURE;
841 : }
842 :
843 4 : if (osSourceLayerFieldName.empty())
844 : {
845 0 : CPLError(
846 : CE_Failure, CPLE_NotSupported,
847 : "SetFeature() not supported when SourceLayerFieldName is not set");
848 0 : return OGRERR_FAILURE;
849 : }
850 :
851 4 : if (poFeature->GetFID() == OGRNullFID)
852 : {
853 1 : CPLError(CE_Failure, CPLE_NotSupported,
854 : "SetFeature() not supported when FID is not set");
855 1 : return OGRERR_FAILURE;
856 : }
857 :
858 3 : if (!poFeature->IsFieldSetAndNotNull(0))
859 : {
860 1 : CPLError(CE_Failure, CPLE_NotSupported,
861 : "SetFeature() not supported when '%s' field is not set",
862 : osSourceLayerFieldName.c_str());
863 1 : return OGRERR_FAILURE;
864 : }
865 :
866 2 : const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
867 5 : for (int i = 0; i < nSrcLayers; i++)
868 : {
869 4 : if (strcmp(pszSrcLayerName, papoSrcLayers[i]->GetName()) == 0)
870 : {
871 1 : pabModifiedLayers[i] = TRUE;
872 :
873 : OGRFeature *poSrcFeature =
874 1 : new OGRFeature(papoSrcLayers[i]->GetLayerDefn());
875 1 : poSrcFeature->SetFrom(poFeature, TRUE);
876 1 : poSrcFeature->SetFID(poFeature->GetFID());
877 1 : OGRErr eErr = papoSrcLayers[i]->SetFeature(poSrcFeature);
878 1 : delete poSrcFeature;
879 1 : return eErr;
880 : }
881 : }
882 :
883 1 : CPLError(CE_Failure, CPLE_NotSupported,
884 : "SetFeature() not supported : '%s' source layer does not exist",
885 : pszSrcLayerName);
886 1 : return OGRERR_FAILURE;
887 : }
888 :
889 : /************************************************************************/
890 : /* IUpsertFeature() */
891 : /************************************************************************/
892 :
893 0 : OGRErr OGRUnionLayer::IUpsertFeature(OGRFeature *poFeature)
894 : {
895 0 : if (GetFeature(poFeature->GetFID()))
896 : {
897 0 : return ISetFeature(poFeature);
898 : }
899 : else
900 : {
901 0 : return ICreateFeature(poFeature);
902 : }
903 : }
904 :
905 : /************************************************************************/
906 : /* IUpdateFeature() */
907 : /************************************************************************/
908 :
909 0 : OGRErr OGRUnionLayer::IUpdateFeature(OGRFeature *poFeature,
910 : int nUpdatedFieldsCount,
911 : const int *panUpdatedFieldsIdx,
912 : int nUpdatedGeomFieldsCount,
913 : const int *panUpdatedGeomFieldsIdx,
914 : bool bUpdateStyleString)
915 : {
916 0 : if (!bPreserveSrcFID)
917 : {
918 0 : CPLError(CE_Failure, CPLE_NotSupported,
919 : "UpdateFeature() not supported when PreserveSrcFID is OFF");
920 0 : return OGRERR_FAILURE;
921 : }
922 :
923 0 : if (osSourceLayerFieldName.empty())
924 : {
925 0 : CPLError(CE_Failure, CPLE_NotSupported,
926 : "UpdateFeature() not supported when SourceLayerFieldName is "
927 : "not set");
928 0 : return OGRERR_FAILURE;
929 : }
930 :
931 0 : if (poFeature->GetFID() == OGRNullFID)
932 : {
933 0 : CPLError(CE_Failure, CPLE_NotSupported,
934 : "UpdateFeature() not supported when FID is not set");
935 0 : return OGRERR_FAILURE;
936 : }
937 :
938 0 : if (!poFeature->IsFieldSetAndNotNull(0))
939 : {
940 0 : CPLError(CE_Failure, CPLE_NotSupported,
941 : "UpdateFeature() not supported when '%s' field is not set",
942 : osSourceLayerFieldName.c_str());
943 0 : return OGRERR_FAILURE;
944 : }
945 :
946 0 : const char *pszSrcLayerName = poFeature->GetFieldAsString(0);
947 0 : for (int i = 0; i < nSrcLayers; i++)
948 : {
949 0 : if (strcmp(pszSrcLayerName, papoSrcLayers[i]->GetName()) == 0)
950 : {
951 0 : pabModifiedLayers[i] = TRUE;
952 :
953 0 : const auto poSrcLayerDefn = papoSrcLayers[i]->GetLayerDefn();
954 0 : OGRFeature *poSrcFeature = new OGRFeature(poSrcLayerDefn);
955 0 : poSrcFeature->SetFrom(poFeature, TRUE);
956 0 : poSrcFeature->SetFID(poFeature->GetFID());
957 :
958 : // We could potentially have a pre-computed map from indices in
959 : // poLayerDefn to indices in poSrcLayerDefn
960 0 : std::vector<int> anSrcUpdatedFieldIdx;
961 0 : const auto poLayerDefn = GetLayerDefn();
962 0 : for (int j = 0; j < nUpdatedFieldsCount; ++j)
963 : {
964 0 : if (panUpdatedFieldsIdx[j] != 0)
965 : {
966 0 : const int nNewIdx = poSrcLayerDefn->GetFieldIndex(
967 0 : poLayerDefn->GetFieldDefn(panUpdatedFieldsIdx[j])
968 0 : ->GetNameRef());
969 0 : if (nNewIdx >= 0)
970 : {
971 0 : anSrcUpdatedFieldIdx.push_back(nNewIdx);
972 : }
973 : }
974 : }
975 0 : std::vector<int> anSrcUpdatedGeomFieldIdx;
976 0 : for (int j = 0; j < nUpdatedGeomFieldsCount; ++j)
977 : {
978 0 : if (panUpdatedGeomFieldsIdx[j] != 0)
979 : {
980 0 : const int nNewIdx = poSrcLayerDefn->GetGeomFieldIndex(
981 : poLayerDefn
982 0 : ->GetGeomFieldDefn(panUpdatedGeomFieldsIdx[j])
983 0 : ->GetNameRef());
984 0 : if (nNewIdx >= 0)
985 : {
986 0 : anSrcUpdatedGeomFieldIdx.push_back(nNewIdx);
987 : }
988 : }
989 : }
990 :
991 0 : OGRErr eErr = papoSrcLayers[i]->UpdateFeature(
992 0 : poSrcFeature, static_cast<int>(anSrcUpdatedFieldIdx.size()),
993 0 : anSrcUpdatedFieldIdx.data(),
994 0 : static_cast<int>(anSrcUpdatedGeomFieldIdx.size()),
995 0 : anSrcUpdatedGeomFieldIdx.data(), bUpdateStyleString);
996 0 : delete poSrcFeature;
997 0 : return eErr;
998 : }
999 : }
1000 :
1001 0 : CPLError(CE_Failure, CPLE_NotSupported,
1002 : "UpdateFeature() not supported : '%s' source layer does not exist",
1003 : pszSrcLayerName);
1004 0 : return OGRERR_FAILURE;
1005 : }
1006 :
1007 : /************************************************************************/
1008 : /* GetSpatialRef() */
1009 : /************************************************************************/
1010 :
1011 94 : OGRSpatialReference *OGRUnionLayer::GetSpatialRef()
1012 : {
1013 94 : if (nGeomFields < 0)
1014 0 : return nullptr;
1015 94 : if (nGeomFields >= 1 && papoGeomFields[0]->bSRSSet)
1016 : return const_cast<OGRSpatialReference *>(
1017 1 : papoGeomFields[0]->GetSpatialRef());
1018 :
1019 93 : if (poGlobalSRS == nullptr)
1020 : {
1021 57 : poGlobalSRS = papoSrcLayers[0]->GetSpatialRef();
1022 57 : if (poGlobalSRS != nullptr)
1023 22 : const_cast<OGRSpatialReference *>(poGlobalSRS)->Reference();
1024 : }
1025 93 : return const_cast<OGRSpatialReference *>(poGlobalSRS);
1026 : }
1027 :
1028 : /************************************************************************/
1029 : /* GetAttrFilterPassThroughValue() */
1030 : /************************************************************************/
1031 :
1032 1736 : int OGRUnionLayer::GetAttrFilterPassThroughValue()
1033 : {
1034 1736 : if (m_poAttrQuery == nullptr)
1035 1244 : return TRUE;
1036 :
1037 492 : if (bAttrFilterPassThroughValue >= 0)
1038 402 : return bAttrFilterPassThroughValue;
1039 :
1040 90 : char **papszUsedFields = m_poAttrQuery->GetUsedFields();
1041 90 : int bRet = TRUE;
1042 :
1043 270 : for (int iLayer = 0; iLayer < nSrcLayers; iLayer++)
1044 : {
1045 : OGRFeatureDefn *poSrcFeatureDefn =
1046 180 : papoSrcLayers[iLayer]->GetLayerDefn();
1047 180 : char **papszIter = papszUsedFields;
1048 241 : while (papszIter != nullptr && *papszIter != nullptr)
1049 : {
1050 74 : int bIsSpecial = FALSE;
1051 428 : for (int i = 0; i < SPECIAL_FIELD_COUNT; i++)
1052 : {
1053 358 : if (EQUAL(*papszIter, SpecialFieldNames[i]))
1054 : {
1055 4 : bIsSpecial = TRUE;
1056 4 : break;
1057 : }
1058 : }
1059 74 : if (!bIsSpecial && poSrcFeatureDefn->GetFieldIndex(*papszIter) < 0)
1060 : {
1061 13 : bRet = FALSE;
1062 13 : break;
1063 : }
1064 61 : papszIter++;
1065 : }
1066 : }
1067 :
1068 90 : CSLDestroy(papszUsedFields);
1069 :
1070 90 : bAttrFilterPassThroughValue = bRet;
1071 :
1072 90 : return bRet;
1073 : }
1074 :
1075 : /************************************************************************/
1076 : /* ApplyAttributeFilterToSrcLayer() */
1077 : /************************************************************************/
1078 :
1079 1595 : void OGRUnionLayer::ApplyAttributeFilterToSrcLayer(int iSubLayer)
1080 : {
1081 1595 : CPLAssert(iSubLayer >= 0 && iSubLayer < nSrcLayers);
1082 :
1083 1595 : if (GetAttrFilterPassThroughValue())
1084 1536 : papoSrcLayers[iSubLayer]->SetAttributeFilter(pszAttributeFilter);
1085 : else
1086 59 : papoSrcLayers[iSubLayer]->SetAttributeFilter(nullptr);
1087 1595 : }
1088 :
1089 : /************************************************************************/
1090 : /* GetFeatureCount() */
1091 : /************************************************************************/
1092 :
1093 139 : GIntBig OGRUnionLayer::GetFeatureCount(int bForce)
1094 : {
1095 139 : if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1096 1 : m_poAttrQuery == nullptr)
1097 : {
1098 1 : return nFeatureCount;
1099 : }
1100 :
1101 138 : if (!GetAttrFilterPassThroughValue())
1102 5 : return OGRLayer::GetFeatureCount(bForce);
1103 :
1104 133 : GIntBig nRet = 0;
1105 399 : for (int i = 0; i < nSrcLayers; i++)
1106 : {
1107 266 : AutoWarpLayerIfNecessary(i);
1108 266 : ApplyAttributeFilterToSrcLayer(i);
1109 266 : SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
1110 266 : nRet += papoSrcLayers[i]->GetFeatureCount(bForce);
1111 : }
1112 133 : ResetReading();
1113 133 : return nRet;
1114 : }
1115 :
1116 : /************************************************************************/
1117 : /* SetAttributeFilter() */
1118 : /************************************************************************/
1119 :
1120 389 : OGRErr OGRUnionLayer::SetAttributeFilter(const char *pszAttributeFilterIn)
1121 : {
1122 389 : if (pszAttributeFilterIn == nullptr && pszAttributeFilter == nullptr)
1123 180 : return OGRERR_NONE;
1124 209 : if (pszAttributeFilterIn != nullptr && pszAttributeFilter != nullptr &&
1125 54 : strcmp(pszAttributeFilterIn, pszAttributeFilter) == 0)
1126 7 : return OGRERR_NONE;
1127 :
1128 202 : if (poFeatureDefn == nullptr)
1129 1 : GetLayerDefn();
1130 :
1131 202 : bAttrFilterPassThroughValue = -1;
1132 :
1133 202 : OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttributeFilterIn);
1134 202 : if (eErr != OGRERR_NONE)
1135 0 : return eErr;
1136 :
1137 202 : CPLFree(pszAttributeFilter);
1138 202 : pszAttributeFilter =
1139 202 : pszAttributeFilterIn ? CPLStrdup(pszAttributeFilterIn) : nullptr;
1140 :
1141 202 : if (iCurLayer >= 0 && iCurLayer < nSrcLayers)
1142 202 : ApplyAttributeFilterToSrcLayer(iCurLayer);
1143 :
1144 202 : return OGRERR_NONE;
1145 : }
1146 :
1147 : /************************************************************************/
1148 : /* TestCapability() */
1149 : /************************************************************************/
1150 :
1151 308 : int OGRUnionLayer::TestCapability(const char *pszCap)
1152 : {
1153 308 : if (EQUAL(pszCap, OLCFastFeatureCount))
1154 : {
1155 4 : if (nFeatureCount >= 0 && m_poFilterGeom == nullptr &&
1156 3 : m_poAttrQuery == nullptr)
1157 1 : return TRUE;
1158 :
1159 3 : if (!GetAttrFilterPassThroughValue())
1160 1 : return FALSE;
1161 :
1162 6 : for (int i = 0; i < nSrcLayers; i++)
1163 : {
1164 4 : AutoWarpLayerIfNecessary(i);
1165 4 : ApplyAttributeFilterToSrcLayer(i);
1166 4 : SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
1167 4 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1168 0 : return FALSE;
1169 : }
1170 2 : return TRUE;
1171 : }
1172 :
1173 304 : if (EQUAL(pszCap, OLCFastGetExtent))
1174 : {
1175 19 : if (nGeomFields >= 1 && papoGeomFields[0]->sStaticEnvelope.IsInit())
1176 1 : return TRUE;
1177 :
1178 28 : for (int i = 0; i < nSrcLayers; i++)
1179 : {
1180 23 : AutoWarpLayerIfNecessary(i);
1181 23 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1182 13 : return FALSE;
1183 : }
1184 5 : return TRUE;
1185 : }
1186 :
1187 285 : if (EQUAL(pszCap, OLCFastSpatialFilter))
1188 : {
1189 6 : for (int i = 0; i < nSrcLayers; i++)
1190 : {
1191 4 : AutoWarpLayerIfNecessary(i);
1192 4 : ApplyAttributeFilterToSrcLayer(i);
1193 4 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1194 0 : return FALSE;
1195 : }
1196 2 : return TRUE;
1197 : }
1198 :
1199 283 : if (EQUAL(pszCap, OLCStringsAsUTF8))
1200 : {
1201 160 : for (int i = 0; i < nSrcLayers; i++)
1202 : {
1203 130 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1204 70 : return FALSE;
1205 : }
1206 30 : return TRUE;
1207 : }
1208 :
1209 183 : if (EQUAL(pszCap, OLCRandomRead))
1210 : {
1211 0 : if (!bPreserveSrcFID)
1212 0 : return FALSE;
1213 :
1214 0 : for (int i = 0; i < nSrcLayers; i++)
1215 : {
1216 0 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1217 0 : return FALSE;
1218 : }
1219 0 : return TRUE;
1220 : }
1221 :
1222 183 : if (EQUAL(pszCap, OLCRandomWrite))
1223 : {
1224 10 : if (!bPreserveSrcFID || osSourceLayerFieldName.empty())
1225 9 : return FALSE;
1226 :
1227 3 : for (int i = 0; i < nSrcLayers; i++)
1228 : {
1229 2 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1230 0 : return FALSE;
1231 : }
1232 1 : return TRUE;
1233 : }
1234 :
1235 173 : if (EQUAL(pszCap, OLCSequentialWrite))
1236 : {
1237 10 : if (osSourceLayerFieldName.empty())
1238 9 : return FALSE;
1239 :
1240 3 : for (int i = 0; i < nSrcLayers; i++)
1241 : {
1242 2 : if (!papoSrcLayers[i]->TestCapability(pszCap))
1243 0 : return FALSE;
1244 : }
1245 1 : return TRUE;
1246 : }
1247 :
1248 163 : if (EQUAL(pszCap, OLCIgnoreFields))
1249 11 : return TRUE;
1250 :
1251 152 : if (EQUAL(pszCap, OLCCurveGeometries))
1252 34 : return TRUE;
1253 :
1254 118 : return FALSE;
1255 : }
1256 :
1257 : /************************************************************************/
1258 : /* GetExtent() */
1259 : /************************************************************************/
1260 :
1261 45 : OGRErr OGRUnionLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
1262 : int bForce)
1263 : {
1264 53 : if (iGeomField >= 0 && iGeomField < nGeomFields &&
1265 8 : papoGeomFields[iGeomField]->sStaticEnvelope.IsInit())
1266 : {
1267 3 : *psExtent = papoGeomFields[iGeomField]->sStaticEnvelope;
1268 3 : return OGRERR_NONE;
1269 : }
1270 :
1271 42 : if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
1272 : {
1273 16 : if (iGeomField != 0)
1274 : {
1275 15 : CPLError(CE_Failure, CPLE_AppDefined,
1276 : "Invalid geometry field index : %d", iGeomField);
1277 : }
1278 16 : return OGRERR_FAILURE;
1279 : }
1280 :
1281 26 : int bInit = FALSE;
1282 78 : for (int i = 0; i < nSrcLayers; i++)
1283 : {
1284 52 : AutoWarpLayerIfNecessary(i);
1285 104 : int iSrcGeomField = papoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
1286 52 : GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
1287 52 : if (iSrcGeomField >= 0)
1288 : {
1289 49 : if (!bInit)
1290 : {
1291 52 : if (papoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent,
1292 26 : bForce) == OGRERR_NONE)
1293 24 : bInit = TRUE;
1294 : }
1295 : else
1296 : {
1297 23 : OGREnvelope sExtent;
1298 46 : if (papoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent,
1299 23 : bForce) == OGRERR_NONE)
1300 : {
1301 23 : psExtent->Merge(sExtent);
1302 : }
1303 : }
1304 : }
1305 : }
1306 26 : return (bInit) ? OGRERR_NONE : OGRERR_FAILURE;
1307 : }
1308 :
1309 : /************************************************************************/
1310 : /* GetExtent() */
1311 : /************************************************************************/
1312 :
1313 9 : OGRErr OGRUnionLayer::GetExtent(OGREnvelope *psExtent, int bForce)
1314 : {
1315 9 : return GetExtent(0, psExtent, bForce);
1316 : }
1317 :
1318 : /************************************************************************/
1319 : /* SetSpatialFilter() */
1320 : /************************************************************************/
1321 :
1322 144 : void OGRUnionLayer::SetSpatialFilter(OGRGeometry *poGeomIn)
1323 : {
1324 144 : SetSpatialFilter(0, poGeomIn);
1325 144 : }
1326 :
1327 : /************************************************************************/
1328 : /* SetSpatialFilter() */
1329 : /************************************************************************/
1330 :
1331 351 : void OGRUnionLayer::SetSpatialFilter(int iGeomField, OGRGeometry *poGeom)
1332 : {
1333 351 : if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
1334 : {
1335 31 : if (poGeom != nullptr)
1336 : {
1337 14 : CPLError(CE_Failure, CPLE_AppDefined,
1338 : "Invalid geometry field index : %d", iGeomField);
1339 14 : return;
1340 : }
1341 : }
1342 :
1343 337 : m_iGeomFieldFilter = iGeomField;
1344 337 : if (InstallFilter(poGeom))
1345 117 : ResetReading();
1346 :
1347 337 : if (iCurLayer >= 0 && iCurLayer < nSrcLayers)
1348 : {
1349 248 : SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
1350 : }
1351 : }
1352 :
1353 : /************************************************************************/
1354 : /* TranslateFromSrcLayer() */
1355 : /************************************************************************/
1356 :
1357 2564 : OGRFeature *OGRUnionLayer::TranslateFromSrcLayer(OGRFeature *poSrcFeature)
1358 : {
1359 2564 : CPLAssert(poSrcFeature->GetFieldCount() == 0 || panMap != nullptr);
1360 2564 : CPLAssert(iCurLayer >= 0 && iCurLayer < nSrcLayers);
1361 :
1362 2564 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
1363 2564 : poFeature->SetFrom(poSrcFeature, panMap, TRUE);
1364 :
1365 2667 : if (!osSourceLayerFieldName.empty() &&
1366 103 : !poFeatureDefn->GetFieldDefn(0)->IsIgnored())
1367 : {
1368 103 : poFeature->SetField(0, papoSrcLayers[iCurLayer]->GetName());
1369 : }
1370 :
1371 5583 : for (int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
1372 : {
1373 3019 : if (poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored())
1374 110 : poFeature->SetGeomFieldDirectly(i, nullptr);
1375 : else
1376 : {
1377 2909 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
1378 2909 : if (poGeom != nullptr)
1379 : {
1380 2730 : poGeom->assignSpatialReference(
1381 2730 : poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
1382 : }
1383 : }
1384 : }
1385 :
1386 2564 : if (bPreserveSrcFID)
1387 102 : poFeature->SetFID(poSrcFeature->GetFID());
1388 : else
1389 2462 : poFeature->SetFID(nNextFID++);
1390 2564 : return poFeature;
1391 : }
1392 :
1393 : /************************************************************************/
1394 : /* SetIgnoredFields() */
1395 : /************************************************************************/
1396 :
1397 130 : OGRErr OGRUnionLayer::SetIgnoredFields(CSLConstList papszFields)
1398 : {
1399 130 : OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
1400 130 : if (eErr != OGRERR_NONE)
1401 0 : return eErr;
1402 :
1403 130 : m_aosIgnoredFields = papszFields;
1404 :
1405 130 : return eErr;
1406 : }
1407 :
1408 : /************************************************************************/
1409 : /* SyncToDisk() */
1410 : /************************************************************************/
1411 :
1412 1 : OGRErr OGRUnionLayer::SyncToDisk()
1413 : {
1414 3 : for (int i = 0; i < nSrcLayers; i++)
1415 : {
1416 2 : if (pabModifiedLayers[i])
1417 : {
1418 1 : papoSrcLayers[i]->SyncToDisk();
1419 1 : pabModifiedLayers[i] = FALSE;
1420 : }
1421 : }
1422 :
1423 1 : return OGRERR_NONE;
1424 : }
1425 :
1426 : #endif /* #ifndef DOXYGEN_SKIP */
|