Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Formal test harness for OGRLayer implementations.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam
9 : * Copyright (c) 2009-2014, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_multiproc.h"
32 : #include "gdal_version.h"
33 : #include "ogr_api.h"
34 : #include "ogr_p.h"
35 : #include "ogrsf_frmts.h"
36 : #include "ogr_swq.h"
37 : #include "ogr_recordbatch.h"
38 : #include "commonutils.h"
39 :
40 : #include <cinttypes>
41 : #include <algorithm>
42 : #include <limits>
43 :
44 : bool bReadOnly = false;
45 : bool bVerbose = true;
46 : const char *pszDataSource = nullptr;
47 : char **papszLayers = nullptr;
48 : const char *pszSQLStatement = nullptr;
49 : const char *pszDialect = nullptr;
50 : int nLoops = 1;
51 : bool bFullSpatialFilter = false;
52 : char **papszOpenOptions = nullptr;
53 : const char *pszDriver = nullptr;
54 : bool bAllDrivers = false;
55 : const char *pszLogFilename = nullptr;
56 : char **papszDSCO = nullptr;
57 : char **papszLCO = nullptr;
58 :
59 : typedef struct
60 : {
61 : CPLJoinableThread *hThread;
62 : int bRet;
63 : } ThreadContext;
64 :
65 : static void Usage();
66 : static void ThreadFunction(void *user_data);
67 : static void ThreadFunctionInternal(ThreadContext *psContext);
68 : static int TestDataset(GDALDriver **ppoDriver);
69 : static int TestCreate(GDALDriver *poDriver, int bFromAllDrivers);
70 : static int TestOGRLayer(GDALDataset *poDS, OGRLayer *poLayer, int bIsSQLLayer);
71 : static int TestInterleavedReading(const char *pszDataSource,
72 : char **papszLayers);
73 : static int TestDSErrorConditions(GDALDataset *poDS);
74 : static int TestVirtualIO(GDALDataset *poDS);
75 :
76 117735 : static const char *Log(const char *pszMsg, int nLineNumber)
77 : {
78 117735 : if (pszLogFilename == nullptr)
79 117735 : return pszMsg;
80 0 : FILE *f = fopen(pszLogFilename, "at");
81 0 : if (f == nullptr)
82 0 : return pszMsg;
83 0 : fprintf(f, "%d: %s\n", nLineNumber, pszMsg);
84 0 : fclose(f);
85 0 : return pszMsg;
86 : }
87 :
88 : #define LOG_STR(str) (Log((str), __LINE__))
89 : #define LOG_ACTION(action) ((void)Log(#action, __LINE__), (action))
90 :
91 : /************************************************************************/
92 : /* DestroyFeatureAndNullify() */
93 : /************************************************************************/
94 :
95 60045 : static void DestroyFeatureAndNullify(OGRFeature *&poFeature)
96 : {
97 60045 : OGRFeature::DestroyFeature(poFeature);
98 60045 : poFeature = nullptr;
99 60045 : }
100 :
101 : /************************************************************************/
102 : /* main() */
103 : /************************************************************************/
104 :
105 111 : MAIN_START(nArgc, papszArgv)
106 :
107 : {
108 111 : EarlySetConfigOptions(nArgc, papszArgv);
109 :
110 111 : OGRRegisterAll();
111 :
112 : /* -------------------------------------------------------------------- */
113 : /* Processing command line arguments. */
114 : /* -------------------------------------------------------------------- */
115 111 : nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
116 :
117 111 : if (nArgc < 1)
118 0 : exit(-nArgc);
119 :
120 111 : int bRet = TRUE;
121 111 : int nThreads = 1;
122 :
123 111 : if (EQUAL(CPLGetConfigOption("DRIVER_WISHED", ""), "FileGDB"))
124 : {
125 1 : auto poFileGDB = GetGDALDriverManager()->GetDriverByName("FileGDB");
126 : auto poOpenFileGDB =
127 1 : GetGDALDriverManager()->GetDriverByName("OpenFileGDB");
128 1 : if (poFileGDB && poOpenFileGDB)
129 : {
130 1 : GetGDALDriverManager()->DeregisterDriver(poFileGDB);
131 1 : GetGDALDriverManager()->DeregisterDriver(poOpenFileGDB);
132 1 : GetGDALDriverManager()->RegisterDriver(poFileGDB);
133 1 : GetGDALDriverManager()->RegisterDriver(poOpenFileGDB);
134 : }
135 : }
136 :
137 : /* -------------------------------------------------------------------- */
138 : /* Processing command line arguments. */
139 : /* -------------------------------------------------------------------- */
140 315 : for (int iArg = 1; iArg < nArgc; iArg++)
141 : {
142 209 : if (EQUAL(papszArgv[iArg], "--utility_version"))
143 : {
144 5 : printf("%s was compiled against GDAL %s and "
145 : "is running against GDAL %s\n",
146 : papszArgv[0], GDAL_RELEASE_NAME,
147 : GDALVersionInfo("RELEASE_NAME"));
148 5 : CSLDestroy(papszArgv);
149 5 : return 0;
150 : }
151 204 : else if (EQUAL(papszArgv[iArg], "-ro"))
152 : {
153 75 : bReadOnly = true;
154 : }
155 129 : else if (EQUAL(papszArgv[iArg], "-q") ||
156 129 : EQUAL(papszArgv[iArg], "-quiet"))
157 : {
158 0 : bVerbose = false;
159 : }
160 129 : else if (EQUAL(papszArgv[iArg], "-sql") && iArg + 1 < nArgc)
161 : {
162 10 : pszSQLStatement = papszArgv[++iArg];
163 : }
164 119 : else if (EQUAL(papszArgv[iArg], "-dialect") && iArg + 1 < nArgc)
165 : {
166 0 : pszDialect = papszArgv[++iArg];
167 : }
168 119 : else if (EQUAL(papszArgv[iArg], "-threads") && iArg + 1 < nArgc)
169 : {
170 0 : nThreads = atoi(papszArgv[++iArg]);
171 : }
172 119 : else if (EQUAL(papszArgv[iArg], "-loops") && iArg + 1 < nArgc)
173 : {
174 0 : nLoops = atoi(papszArgv[++iArg]);
175 : }
176 119 : else if (EQUAL(papszArgv[iArg], "-fsf"))
177 : {
178 3 : bFullSpatialFilter = true;
179 : }
180 116 : else if (EQUAL(papszArgv[iArg], "-oo") && iArg + 1 < nArgc)
181 : {
182 0 : papszOpenOptions =
183 0 : CSLAddString(papszOpenOptions, papszArgv[++iArg]);
184 : }
185 116 : else if (EQUAL(papszArgv[iArg], "-dsco") && iArg + 1 < nArgc)
186 : {
187 1 : papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg]);
188 : }
189 115 : else if (EQUAL(papszArgv[iArg], "-lco") && iArg + 1 < nArgc)
190 : {
191 0 : papszLCO = CSLAddString(papszLCO, papszArgv[++iArg]);
192 : }
193 115 : else if (EQUAL(papszArgv[iArg], "-log") && iArg + 1 < nArgc)
194 : {
195 0 : pszLogFilename = papszArgv[++iArg];
196 : }
197 115 : else if (EQUAL(papszArgv[iArg], "-driver") && iArg + 1 < nArgc)
198 : {
199 1 : pszDriver = papszArgv[++iArg];
200 : }
201 114 : else if (EQUAL(papszArgv[iArg], "-all_drivers"))
202 : {
203 1 : bAllDrivers = true;
204 : }
205 113 : else if (papszArgv[iArg][0] == '-')
206 : {
207 0 : Usage();
208 : }
209 113 : else if (pszDataSource == nullptr)
210 : {
211 104 : pszDataSource = papszArgv[iArg];
212 : }
213 : else
214 : {
215 9 : papszLayers = CSLAddString(papszLayers, papszArgv[iArg]);
216 : }
217 : }
218 :
219 106 : if (pszDataSource == nullptr && pszDriver == nullptr && !bAllDrivers)
220 0 : Usage();
221 :
222 106 : if (nThreads > 1 && !bReadOnly && pszDataSource != nullptr)
223 : {
224 0 : fprintf(
225 : stderr,
226 : "-threads must be used with -ro or -driver/-all_drivers option.\n");
227 0 : exit(1);
228 : }
229 :
230 106 : if (nThreads == 1)
231 : {
232 : ThreadContext sContext;
233 106 : ThreadFunction(&sContext);
234 106 : bRet = sContext.bRet;
235 : }
236 0 : else if (nThreads > 1)
237 : {
238 0 : ThreadContext *pasContext = new ThreadContext[nThreads];
239 0 : for (int i = 0; i < nThreads; i++)
240 : {
241 0 : pasContext[i].hThread =
242 0 : CPLCreateJoinableThread(ThreadFunction, &(pasContext[i]));
243 : }
244 0 : for (int i = 0; i < nThreads; i++)
245 : {
246 0 : CPLJoinThread(pasContext[i].hThread);
247 0 : bRet &= pasContext[i].bRet;
248 : }
249 0 : delete[] pasContext;
250 : }
251 :
252 106 : OGRCleanupAll();
253 :
254 106 : CSLDestroy(papszLayers);
255 106 : CSLDestroy(papszArgv);
256 106 : CSLDestroy(papszOpenOptions);
257 106 : CSLDestroy(papszDSCO);
258 106 : CSLDestroy(papszLCO);
259 :
260 : #ifdef DBMALLOC
261 : malloc_dump(1);
262 : #endif
263 :
264 106 : return (bRet) ? 0 : 1;
265 : }
266 :
267 0 : MAIN_END
268 :
269 : /************************************************************************/
270 : /* ThreadFunction() */
271 : /************************************************************************/
272 :
273 106 : static void ThreadFunction(void *user_data)
274 :
275 : {
276 106 : ThreadContext *psContext = static_cast<ThreadContext *>(user_data);
277 106 : psContext->bRet = TRUE;
278 : #ifdef __AFL_HAVE_MANUAL_CONTROL
279 : while (__AFL_LOOP(1000))
280 : {
281 : #endif
282 212 : for (int iLoop = 0; psContext->bRet && iLoop < nLoops; iLoop++)
283 : {
284 106 : ThreadFunctionInternal(psContext);
285 : }
286 : #ifdef __AFL_HAVE_MANUAL_CONTROL
287 : }
288 : #endif
289 106 : }
290 :
291 : /************************************************************************/
292 : /* ThreadFunctionInternal() */
293 : /************************************************************************/
294 :
295 106 : static void ThreadFunctionInternal(ThreadContext *psContext)
296 :
297 : {
298 106 : int bRet = TRUE;
299 :
300 106 : GDALDriver *poDriver = nullptr;
301 :
302 106 : if (pszDataSource != nullptr)
303 : {
304 104 : bRet = TestDataset(&poDriver);
305 : }
306 2 : else if (pszDriver != nullptr)
307 : {
308 1 : poDriver = static_cast<GDALDriver *>(GDALGetDriverByName(pszDriver));
309 1 : if (poDriver)
310 : {
311 1 : bRet &= TestCreate(poDriver, FALSE);
312 : }
313 : else
314 : {
315 0 : printf("ERROR: Cannot find driver %s\n", pszDriver);
316 0 : bRet = FALSE;
317 : }
318 : }
319 : else
320 : {
321 1 : const int nCount = GDALGetDriverCount();
322 234 : for (int i = 0; i < nCount; i++)
323 : {
324 233 : poDriver = static_cast<GDALDriver *>(GDALGetDriver(i));
325 233 : if (poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr)
326 90 : bRet &= TestCreate(poDriver, TRUE);
327 : }
328 : }
329 :
330 106 : psContext->bRet = bRet;
331 106 : }
332 :
333 : /************************************************************************/
334 : /* TestDataset() */
335 : /************************************************************************/
336 :
337 104 : static int TestDataset(GDALDriver **ppoDriver)
338 : {
339 104 : int bRet = TRUE;
340 : int bRetLocal;
341 :
342 : /* -------------------------------------------------------------------- */
343 : /* Open data source. */
344 : /* -------------------------------------------------------------------- */
345 :
346 104 : GDALDataset *poDS = static_cast<GDALDataset *>(GDALOpenEx(
347 : pszDataSource,
348 : (!bReadOnly ? GDAL_OF_UPDATE : GDAL_OF_READONLY) | GDAL_OF_VECTOR,
349 : nullptr, papszOpenOptions, nullptr));
350 :
351 104 : if (poDS == nullptr && !bReadOnly)
352 : {
353 2 : poDS = static_cast<GDALDataset *>(GDALOpenEx(
354 : pszDataSource, GDAL_OF_VECTOR, nullptr, papszOpenOptions, nullptr));
355 2 : if (poDS != nullptr && bVerbose)
356 : {
357 2 : printf("Had to open data source read-only.\n");
358 2 : bReadOnly = true;
359 : }
360 : }
361 :
362 104 : GDALDriver *poDriver = nullptr;
363 104 : if (poDS != nullptr)
364 104 : poDriver = poDS->GetDriver();
365 104 : *ppoDriver = poDriver;
366 :
367 : /* -------------------------------------------------------------------- */
368 : /* Report failure */
369 : /* -------------------------------------------------------------------- */
370 104 : if (poDS == nullptr)
371 : {
372 0 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
373 :
374 0 : printf("FAILURE:\n"
375 : "Unable to open datasource `%s' with the following drivers.\n",
376 : pszDataSource);
377 :
378 0 : for (int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
379 : {
380 0 : printf(" -> %s\n", poR->GetDriver(iDriver)->GetDescription());
381 : }
382 :
383 0 : return FALSE;
384 : }
385 :
386 : /* -------------------------------------------------------------------- */
387 : /* Some information messages. */
388 : /* -------------------------------------------------------------------- */
389 104 : if (bVerbose)
390 104 : printf("INFO: Open of `%s' using driver `%s' successful.\n",
391 104 : pszDataSource, poDriver->GetDescription());
392 :
393 104 : if (bVerbose && !EQUAL(pszDataSource, poDS->GetDescription()))
394 : {
395 0 : printf("INFO: Internal data source name `%s'\n"
396 : " different from user name `%s'.\n",
397 0 : poDS->GetDescription(), pszDataSource);
398 : }
399 :
400 : // Check that pszDomain == nullptr doesn't crash
401 104 : poDS->GetMetadata(nullptr);
402 104 : poDS->GetMetadataItem("", nullptr);
403 :
404 104 : if (!poDriver->GetMetadataItem(GDAL_DCAP_VECTOR))
405 : {
406 0 : printf("FAILURE: Driver does not advertise GDAL_DCAP_VECTOR!\n");
407 0 : bRet = false;
408 : }
409 :
410 : // Test consistency of datasource capabilities and driver metadata
411 130 : if (poDS->TestCapability(ODsCCreateLayer) &&
412 26 : !poDriver->GetMetadataItem(GDAL_DCAP_CREATE_LAYER))
413 : {
414 0 : printf("FAILURE: Dataset advertises ODsCCreateLayer capability but "
415 : "driver metadata does not advertise GDAL_DCAP_CREATE_LAYER!\n");
416 0 : bRet = false;
417 : }
418 235 : if (!bReadOnly &&
419 27 : poDriver->GetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS) &&
420 145 : poDriver->GetMetadataItem(GDAL_DCAP_CREATE_LAYER) &&
421 14 : !poDS->TestCapability(ODsCCreateLayer))
422 : {
423 0 : printf("FAILURE: Driver advertises GDAL_DCAP_CREATE_LAYER and "
424 : "GDAL_DCAP_MULTIPLE_VECTOR_LAYERS capability but dataset does "
425 : "not advertise ODsCCreateLayer!\n");
426 0 : bRet = false;
427 : }
428 :
429 123 : if (poDS->TestCapability(ODsCDeleteLayer) &&
430 19 : !poDriver->GetMetadataItem(GDAL_DCAP_DELETE_LAYER))
431 : {
432 0 : printf("FAILURE: Dataset advertises ODsCDeleteLayer capability but "
433 : "driver metadata does not advertise GDAL_DCAP_DELETE_LAYER!\n");
434 0 : bRet = false;
435 : }
436 :
437 183 : if (poDriver->GetMetadataItem(GDAL_DCAP_CREATE_FIELD) &&
438 79 : !poDriver->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES))
439 : {
440 0 : bRet = FALSE;
441 0 : printf("FAILURE: Driver metadata advertises GDAL_DCAP_CREATE_FIELD but "
442 : "does not include GDAL_DMD_CREATIONFIELDDATATYPES!\n");
443 : }
444 183 : if (poDriver->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES) &&
445 79 : !poDriver->GetMetadataItem(GDAL_DCAP_CREATE_FIELD))
446 : {
447 0 : bRet = FALSE;
448 0 : printf(
449 : "FAILURE: Driver metadata includes GDAL_DMD_CREATIONFIELDDATATYPES "
450 : "but does not advertise GDAL_DCAP_CREATE_FIELD!\n");
451 : }
452 156 : if (poDriver->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES) &&
453 52 : !poDriver->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES))
454 : {
455 0 : bRet = FALSE;
456 0 : printf("FAILURE: Driver metadata includes "
457 : "GDAL_DMD_CREATIONFIELDDATASUBTYPES but does not include "
458 : "GDAL_DMD_CREATIONFIELDDATATYPES!\n");
459 : }
460 :
461 : /* -------------------------------------------------------------------- */
462 : /* Process optional SQL request. */
463 : /* -------------------------------------------------------------------- */
464 104 : if (pszSQLStatement != nullptr)
465 : {
466 : OGRLayer *poResultSet =
467 10 : poDS->ExecuteSQL(pszSQLStatement, nullptr, pszDialect);
468 10 : if (poResultSet == nullptr)
469 : {
470 0 : GDALClose(poDS);
471 0 : return FALSE;
472 : }
473 :
474 10 : if (bVerbose)
475 : {
476 10 : printf("INFO: Testing layer %s.\n", poResultSet->GetName());
477 : }
478 10 : bRet = TestOGRLayer(poDS, poResultSet, TRUE);
479 :
480 10 : poDS->ReleaseResultSet(poResultSet);
481 :
482 10 : bRetLocal = TestDSErrorConditions(poDS);
483 10 : bRet &= bRetLocal;
484 :
485 10 : bRetLocal = TestVirtualIO(poDS);
486 10 : bRet &= bRetLocal;
487 : }
488 : /* -------------------------------------------------------------------- */
489 : /* Process each data source layer. */
490 : /* -------------------------------------------------------------------- */
491 94 : else if (papszLayers == nullptr)
492 : {
493 370 : for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++)
494 : {
495 283 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
496 :
497 283 : if (poLayer == nullptr)
498 : {
499 0 : printf("FAILURE: Couldn't fetch advertised layer %d!\n",
500 : iLayer);
501 0 : GDALClose(poDS);
502 0 : return FALSE;
503 : }
504 :
505 283 : if (bVerbose)
506 : {
507 283 : printf("INFO: Testing layer %s.\n", poLayer->GetName());
508 : }
509 283 : bRet &= TestOGRLayer(poDS, poLayer, FALSE);
510 : }
511 :
512 87 : bRetLocal = TestDSErrorConditions(poDS);
513 87 : bRet &= bRetLocal;
514 :
515 87 : bRetLocal = TestVirtualIO(poDS);
516 87 : bRet &= bRetLocal;
517 :
518 87 : if (poDS->GetLayerCount() >= 2)
519 : {
520 18 : GDALClose(poDS);
521 18 : poDS = nullptr;
522 18 : bRetLocal = TestInterleavedReading(pszDataSource, nullptr);
523 18 : bRet &= bRetLocal;
524 : }
525 : }
526 : else
527 : {
528 : /* --------------------------------------------------------------------
529 : */
530 : /* Or process layers specified by the user */
531 : /* --------------------------------------------------------------------
532 : */
533 7 : char **papszLayerIter = papszLayers;
534 16 : while (*papszLayerIter)
535 : {
536 9 : OGRLayer *poLayer = poDS->GetLayerByName(*papszLayerIter);
537 :
538 9 : if (poLayer == nullptr)
539 : {
540 0 : printf("FAILURE: Couldn't fetch requested layer %s!\n",
541 : *papszLayerIter);
542 0 : GDALClose(poDS);
543 0 : return FALSE;
544 : }
545 :
546 9 : if (bVerbose)
547 : {
548 9 : printf("INFO: Testing layer %s.\n", poLayer->GetName());
549 : }
550 9 : bRet &= TestOGRLayer(poDS, poLayer, FALSE);
551 :
552 9 : papszLayerIter++;
553 : }
554 :
555 7 : bRetLocal = TestDSErrorConditions(poDS);
556 7 : bRet &= bRetLocal;
557 :
558 7 : bRetLocal = TestVirtualIO(poDS);
559 7 : bRet &= bRetLocal;
560 :
561 7 : if (CSLCount(papszLayers) >= 2)
562 : {
563 2 : GDALClose(poDS);
564 2 : poDS = nullptr;
565 2 : bRetLocal = TestInterleavedReading(pszDataSource, papszLayers);
566 2 : bRet &= bRetLocal;
567 : }
568 : }
569 :
570 : /* -------------------------------------------------------------------- */
571 : /* Close down. */
572 : /* -------------------------------------------------------------------- */
573 104 : if (poDS != nullptr)
574 84 : GDALClose(poDS);
575 :
576 104 : return bRet;
577 : }
578 :
579 : /************************************************************************/
580 : /* GetWKT() */
581 : /************************************************************************/
582 :
583 1447 : static const char *GetWKT(OGRwkbGeometryType eGeomType)
584 : {
585 1447 : const char *pszWKT = nullptr;
586 1447 : if (eGeomType == wkbUnknown || eGeomType == wkbPoint)
587 145 : pszWKT = "POINT (0 0)";
588 1302 : else if (eGeomType == wkbLineString)
589 159 : pszWKT = "LINESTRING (0 0,1 1)";
590 1143 : else if (eGeomType == wkbPolygon)
591 93 : pszWKT = "POLYGON ((0 0,0 1,1 1,1 0,0 0))";
592 1050 : else if (eGeomType == wkbMultiPoint)
593 91 : pszWKT = "MULTIPOINT (0 0)";
594 959 : else if (eGeomType == wkbMultiLineString)
595 93 : pszWKT = "MULTILINESTRING ((0 0,1 1))";
596 866 : else if (eGeomType == wkbMultiPolygon)
597 93 : pszWKT = "MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0)))";
598 773 : else if (eGeomType == wkbGeometryCollection)
599 86 : pszWKT = "GEOMETRYCOLLECTION (POINT (0 0),LINESTRING (0 0,1 1),"
600 : "POLYGON ((0 0,0 1,1 1,1 0,0 0)))";
601 687 : else if (eGeomType == wkbPoint25D)
602 89 : pszWKT = "POINT (0 0 10)";
603 598 : else if (eGeomType == wkbLineString25D)
604 92 : pszWKT = "LINESTRING (0 0 10,1 1 10)";
605 506 : else if (eGeomType == wkbPolygon25D)
606 91 : pszWKT = "POLYGON ((0 0 10,0 1 10,1 1 10,1 0 10,0 0 10))";
607 415 : else if (eGeomType == wkbMultiPoint25D)
608 89 : pszWKT = "MULTIPOINT (0 0 10)";
609 326 : else if (eGeomType == wkbMultiLineString25D)
610 91 : pszWKT = "MULTILINESTRING ((0 0 10,1 1 10))";
611 235 : else if (eGeomType == wkbMultiPolygon25D)
612 91 : pszWKT = "MULTIPOLYGON (((0 0 10,0 1 10,1 1 10,1 0 10,0 0 10)))";
613 144 : else if (eGeomType == wkbGeometryCollection25D)
614 87 : pszWKT =
615 : "GEOMETRYCOLLECTION (POINT (0 0 10),LINESTRING (0 0 10,1 1 10),"
616 : "POLYGON ((0 0 10,0 1 10,1 1 10,1 0 10,0 0 10)))";
617 1447 : return pszWKT;
618 : }
619 :
620 : /************************************************************************/
621 : /* TestCreateLayer() */
622 : /************************************************************************/
623 :
624 720 : static int TestCreateLayer(GDALDriver *poDriver, OGRwkbGeometryType eGeomType)
625 : {
626 720 : int bRet = TRUE;
627 720 : const char *pszExt = poDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
628 :
629 : static int nCounter = 0;
630 : CPLString osFilename =
631 1440 : CPLFormFilename("/vsimem", CPLSPrintf("test%d", ++nCounter), pszExt);
632 720 : GDALDataset *poDS = LOG_ACTION(
633 : poDriver->Create(osFilename, 0, 0, 0, GDT_Unknown, papszDSCO));
634 720 : if (poDS == nullptr)
635 : {
636 96 : if (bVerbose)
637 192 : printf("INFO: %s: Creation of %s failed.\n",
638 96 : poDriver->GetDescription(), osFilename.c_str());
639 96 : return bRet;
640 : }
641 624 : CPLPushErrorHandler(CPLQuietErrorHandler);
642 624 : int bCreateLayerCap = LOG_ACTION(poDS->TestCapability(ODsCCreateLayer));
643 624 : OGRLayer *poLayer = LOG_ACTION(poDS->CreateLayer(
644 : CPLGetFilename(osFilename), nullptr, eGeomType, papszLCO));
645 624 : CPLPopErrorHandler();
646 624 : CPLString osLayerNameToTest;
647 624 : OGRwkbGeometryType eExpectedGeomType = wkbUnknown;
648 624 : if (poLayer != nullptr)
649 : {
650 530 : if (bCreateLayerCap == FALSE)
651 : {
652 0 : printf("ERROR: %s: TestCapability(ODsCCreateLayer) returns FALSE "
653 : "whereas layer creation was successful.\n",
654 0 : poDriver->GetDescription());
655 0 : bRet = FALSE;
656 : }
657 :
658 530 : if (LOG_ACTION(poLayer->GetLayerDefn()) == nullptr)
659 : {
660 0 : printf("ERROR: %s: GetLayerDefn() returns NUL just after layer "
661 : "creation.\n",
662 0 : poDriver->GetDescription());
663 0 : bRet = FALSE;
664 : }
665 :
666 530 : auto poLyrDS = LOG_ACTION(poLayer->GetDataset());
667 530 : if (!poLyrDS)
668 : {
669 0 : printf("ERROR: %s: GetDataset() returns NUL just after layer "
670 : "creation.\n",
671 0 : poDriver->GetDescription());
672 0 : bRet = FALSE;
673 : }
674 530 : else if (poLyrDS != poDS)
675 : {
676 16 : printf("WARNING: %s: GetDataset()->GetDescription() (=%s) != %s"
677 : "creation.\n",
678 16 : poDriver->GetDescription(), poLyrDS->GetDescription(),
679 16 : poDS->GetDescription());
680 : }
681 :
682 : // Create fields of various types
683 530 : int bCreateField = LOG_ACTION(poLayer->TestCapability(OLCCreateField));
684 530 : int iFieldStr = -1;
685 530 : int iFieldInt = -1;
686 530 : int iFieldReal = -1;
687 530 : int iFieldDate = -1;
688 530 : int iFieldDateTime = -1;
689 : int bStrFieldOK;
690 : {
691 1060 : OGRFieldDefn oFieldStr("str", OFTString);
692 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
693 530 : bStrFieldOK =
694 530 : LOG_ACTION(poLayer->CreateField(&oFieldStr)) == OGRERR_NONE;
695 530 : CPLPopErrorHandler();
696 1005 : if (bStrFieldOK && (iFieldStr = LOG_ACTION(poLayer->GetLayerDefn())
697 475 : ->GetFieldIndex("str")) < 0)
698 : {
699 0 : printf("ERROR: %s: CreateField(str) returned OK "
700 : "but field was not created.\n",
701 0 : poDriver->GetDescription());
702 0 : bRet = FALSE;
703 : }
704 : }
705 :
706 1060 : OGRFieldDefn oFieldInt("int", OFTInteger);
707 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
708 : const bool bIntFieldOK =
709 530 : LOG_ACTION(poLayer->CreateField(&oFieldInt)) == OGRERR_NONE;
710 530 : CPLPopErrorHandler();
711 1005 : if (bIntFieldOK &&
712 475 : (iFieldInt = poLayer->GetLayerDefn()->GetFieldIndex("int")) < 0)
713 : {
714 0 : printf("ERROR: %s: CreateField(int) returned OK "
715 : "but field was not created.\n",
716 0 : poDriver->GetDescription());
717 0 : bRet = FALSE;
718 : }
719 :
720 1060 : OGRFieldDefn oFieldReal("real", OFTReal);
721 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
722 : const bool bRealFieldOK =
723 530 : LOG_ACTION(poLayer->CreateField(&oFieldReal)) == OGRERR_NONE;
724 530 : CPLPopErrorHandler();
725 1006 : if (bRealFieldOK &&
726 476 : (iFieldReal = poLayer->GetLayerDefn()->GetFieldIndex("real")) < 0)
727 : {
728 0 : printf("ERROR: %s: CreateField(real) returned OK but field was not "
729 : "created.\n",
730 0 : poDriver->GetDescription());
731 0 : bRet = FALSE;
732 : }
733 :
734 1060 : OGRFieldDefn oFieldDate("mydate", OFTDate);
735 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
736 : const bool bDateFieldOK =
737 530 : LOG_ACTION(poLayer->CreateField(&oFieldDate)) == OGRERR_NONE;
738 530 : CPLPopErrorHandler();
739 1005 : if (bDateFieldOK &&
740 475 : (iFieldDate = poLayer->GetLayerDefn()->GetFieldIndex("mydate")) < 0)
741 : {
742 0 : printf("ERROR: %s: CreateField(mydate) returned OK but field was "
743 : "not created.\n",
744 0 : poDriver->GetDescription());
745 0 : bRet = FALSE;
746 : }
747 :
748 1060 : OGRFieldDefn oFieldDateTime("datetime", OFTDateTime);
749 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
750 : const bool bDateTimeFieldOK =
751 530 : LOG_ACTION(poLayer->CreateField(&oFieldDateTime)) == OGRERR_NONE;
752 530 : CPLPopErrorHandler();
753 1005 : if (bDateTimeFieldOK &&
754 : (iFieldDateTime =
755 475 : poLayer->GetLayerDefn()->GetFieldIndex("datetime")) < 0)
756 : {
757 0 : printf("ERROR: %s: CreateField(datetime) returned OK but field was "
758 : "not created.\n",
759 0 : poDriver->GetDescription());
760 0 : bRet = FALSE;
761 : }
762 :
763 530 : if (bCreateField == FALSE &&
764 32 : (bStrFieldOK || bIntFieldOK || bRealFieldOK || bDateFieldOK ||
765 : bDateTimeFieldOK))
766 : {
767 0 : printf("ERROR: %s: TestCapability(OLCCreateField) returns FALSE.\n",
768 0 : poDriver->GetDescription());
769 0 : bRet = FALSE;
770 : }
771 :
772 530 : if (LOG_ACTION(poLayer->TestCapability(OLCSequentialWrite)) == FALSE)
773 : {
774 0 : printf("ERROR: %s: TestCapability(OLCSequentialWrite) returns "
775 : "FALSE.\n",
776 0 : poDriver->GetDescription());
777 0 : bRet = FALSE;
778 : }
779 :
780 : /* Test creating empty feature */
781 530 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
782 530 : CPLErrorReset();
783 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
784 530 : OGRErr eErr = LOG_ACTION(poLayer->CreateFeature(poFeature));
785 530 : CPLPopErrorHandler();
786 530 : if (eErr != OGRERR_NONE && CPLGetLastErrorType() == 0)
787 : {
788 1 : printf("INFO: %s: CreateFeature() at line %d failed but without "
789 : "explicit error.\n",
790 1 : poDriver->GetDescription(), __LINE__);
791 : }
792 530 : if (eErr == OGRERR_NONE && poFeature->GetFID() < 0 &&
793 : eGeomType == wkbUnknown)
794 : {
795 13 : printf("INFO: %s: CreateFeature() at line %d succeeded "
796 : "but failed to assign FID to feature.\n",
797 13 : poDriver->GetDescription(), __LINE__);
798 : }
799 530 : delete poFeature;
800 :
801 : /* Test creating feature with all fields set */
802 530 : poFeature = new OGRFeature(poLayer->GetLayerDefn());
803 530 : if (bStrFieldOK)
804 475 : poFeature->SetField(iFieldStr, "foo");
805 530 : if (bIntFieldOK)
806 475 : poFeature->SetField(iFieldInt, 123);
807 530 : if (bRealFieldOK)
808 476 : poFeature->SetField(iFieldReal, 1.23);
809 530 : if (bDateFieldOK)
810 475 : poFeature->SetField(iFieldDate, "2014/10/20");
811 530 : if (bDateTimeFieldOK)
812 475 : poFeature->SetField(iFieldDateTime, "2014/10/20 12:34:56");
813 530 : CPLErrorReset();
814 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
815 530 : eErr = LOG_ACTION(poLayer->CreateFeature(poFeature));
816 530 : CPLPopErrorHandler();
817 530 : if (eErr != OGRERR_NONE && CPLGetLastErrorType() == 0)
818 : {
819 1 : printf("INFO: %s: CreateFeature() at line %d failed "
820 : "but without explicit error.\n",
821 1 : poDriver->GetDescription(), __LINE__);
822 : }
823 530 : delete poFeature;
824 :
825 : /* Test creating feature with all fields set as well as geometry */
826 530 : poFeature = new OGRFeature(poLayer->GetLayerDefn());
827 530 : if (bStrFieldOK)
828 475 : poFeature->SetField(iFieldStr, "foo");
829 530 : if (bIntFieldOK)
830 475 : poFeature->SetField(iFieldInt, 123);
831 530 : if (bRealFieldOK)
832 476 : poFeature->SetField(iFieldReal, 1.23);
833 530 : if (bDateFieldOK)
834 475 : poFeature->SetField(iFieldDate, "2014/10/20");
835 530 : if (bDateTimeFieldOK)
836 475 : poFeature->SetField(iFieldDateTime, "2014/10/20 12:34:56");
837 :
838 530 : const char *pszWKT = GetWKT(eGeomType);
839 530 : if (pszWKT != nullptr)
840 : {
841 497 : OGRGeometry *poGeom = nullptr;
842 497 : OGRGeometryFactory::createFromWkt(pszWKT, nullptr, &poGeom);
843 497 : poFeature->SetGeometryDirectly(poGeom);
844 : }
845 :
846 530 : CPLErrorReset();
847 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
848 530 : eErr = LOG_ACTION(poLayer->CreateFeature(poFeature));
849 530 : CPLPopErrorHandler();
850 530 : if (eErr != OGRERR_NONE && CPLGetLastErrorType() == 0)
851 : {
852 1 : printf("INFO: %s: CreateFeature() at line %d failed "
853 : "but without explicit error.\n",
854 1 : poDriver->GetDescription(), __LINE__);
855 : }
856 530 : delete poFeature;
857 :
858 : /* Test feature with incompatible geometry */
859 530 : poFeature = new OGRFeature(poLayer->GetLayerDefn());
860 530 : if (bStrFieldOK)
861 475 : poFeature->SetField(iFieldStr, "foo");
862 530 : if (bIntFieldOK)
863 475 : poFeature->SetField(iFieldInt, 123);
864 530 : if (bRealFieldOK)
865 476 : poFeature->SetField(iFieldReal, 1.23);
866 530 : if (bDateFieldOK)
867 475 : poFeature->SetField(iFieldDate, "2014/10/20");
868 530 : if (bDateTimeFieldOK)
869 475 : poFeature->SetField(iFieldDateTime, "2014/10/20 12:34:56");
870 :
871 : OGRwkbGeometryType eOtherGeomType;
872 530 : if (eGeomType == wkbUnknown || eGeomType == wkbNone)
873 64 : eOtherGeomType = wkbLineString;
874 466 : else if (wkbFlatten(eGeomType) == eGeomType)
875 236 : eOtherGeomType = static_cast<OGRwkbGeometryType>(
876 236 : (static_cast<int>(eGeomType) % 7) + 1);
877 : else
878 230 : eOtherGeomType = wkbSetZ(static_cast<OGRwkbGeometryType>(
879 : ((static_cast<int>(wkbFlatten(eGeomType)) % 7) + 1)));
880 530 : pszWKT = GetWKT(eOtherGeomType);
881 530 : if (pszWKT != nullptr)
882 : {
883 530 : OGRGeometry *poGeom = nullptr;
884 530 : OGRGeometryFactory::createFromWkt(pszWKT, nullptr, &poGeom);
885 530 : poFeature->SetGeometryDirectly(poGeom);
886 : }
887 :
888 530 : CPLErrorReset();
889 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
890 530 : eErr = LOG_ACTION(poLayer->CreateFeature(poFeature));
891 530 : CPLPopErrorHandler();
892 530 : if (eErr != OGRERR_NONE && CPLGetLastErrorType() == 0)
893 : {
894 0 : printf("INFO: %s: CreateFeature() at line %d failed "
895 : "but without explicit error.\n",
896 0 : poDriver->GetDescription(), __LINE__);
897 : }
898 530 : delete poFeature;
899 :
900 : /* Test reading a feature: write-only layers might not like this */
901 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
902 530 : LOG_ACTION(poLayer->ResetReading());
903 530 : delete LOG_ACTION(poLayer->GetNextFeature());
904 530 : CPLPopErrorHandler();
905 :
906 530 : osLayerNameToTest = poLayer->GetName();
907 530 : eExpectedGeomType = poLayer->GetGeomType();
908 :
909 : /* Some drivers don't like more than one layer per dataset */
910 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
911 : const int bCreateLayerCap2 =
912 530 : LOG_ACTION(poDS->TestCapability(ODsCCreateLayer));
913 530 : OGRLayer *poLayer2 = LOG_ACTION(poDS->CreateLayer(
914 : CPLSPrintf("%s2", CPLGetFilename(osFilename)), nullptr, eGeomType));
915 530 : CPLPopErrorHandler();
916 530 : if (poLayer2 == nullptr && bCreateLayerCap2)
917 : {
918 48 : printf("INFO: %s: Creation of second layer failed but "
919 : "TestCapability(ODsCCreateLayer) succeeded.\n",
920 48 : poDriver->GetDescription());
921 : }
922 482 : else if (!EQUAL(poDriver->GetDescription(), "CSV") &&
923 : poLayer2 != nullptr)
924 : {
925 774 : OGRFieldDefn oFieldStr("str", OFTString);
926 387 : CPLPushErrorHandler(CPLQuietErrorHandler);
927 387 : LOG_ACTION(poLayer2->CreateField(&oFieldStr));
928 387 : CPLPopErrorHandler();
929 :
930 387 : poFeature = new OGRFeature(poLayer2->GetLayerDefn());
931 387 : pszWKT = GetWKT(eGeomType);
932 387 : if (pszWKT != nullptr)
933 : {
934 363 : OGRGeometry *poGeom = nullptr;
935 363 : OGRGeometryFactory::createFromWkt(pszWKT, nullptr, &poGeom);
936 363 : poFeature->SetGeometryDirectly(poGeom);
937 : }
938 387 : CPLErrorReset();
939 387 : CPLPushErrorHandler(CPLQuietErrorHandler);
940 387 : eErr = LOG_ACTION(poLayer2->CreateFeature(poFeature));
941 387 : CPLPopErrorHandler();
942 387 : delete poFeature;
943 :
944 387 : if (eErr == OGRERR_NONE)
945 : {
946 386 : osLayerNameToTest = poLayer2->GetName();
947 386 : eExpectedGeomType = poLayer2->GetGeomType();
948 : }
949 : }
950 :
951 : /* Test deleting first layer */
952 : const int bDeleteLayerCap =
953 530 : LOG_ACTION(poDS->TestCapability(ODsCDeleteLayer));
954 530 : CPLPushErrorHandler(CPLQuietErrorHandler);
955 530 : eErr = LOG_ACTION(poDS->DeleteLayer(0));
956 530 : CPLPopErrorHandler();
957 530 : if (eErr == OGRERR_NONE)
958 : {
959 125 : if (!bDeleteLayerCap)
960 : {
961 0 : printf("ERROR: %s: TestCapability(ODsCDeleteLayer) "
962 : "returns FALSE but layer deletion worked.\n",
963 0 : poDriver->GetDescription());
964 0 : bRet = FALSE;
965 : }
966 :
967 125 : if (LOG_ACTION(poDS->GetLayerByName(CPLGetFilename(osFilename))) !=
968 : nullptr)
969 : {
970 0 : printf("ERROR: %s: DeleteLayer() declared success, "
971 : "but layer can still be fetched.\n",
972 0 : poDriver->GetDescription());
973 0 : bRet = FALSE;
974 : }
975 : }
976 : else
977 : {
978 405 : if (bDeleteLayerCap)
979 : {
980 0 : printf("ERROR: %s: TestCapability(ODsCDeleteLayer) "
981 : "returns TRUE but layer deletion failed.\n",
982 0 : poDriver->GetDescription());
983 0 : bRet = FALSE;
984 : }
985 : }
986 : }
987 : /*else
988 : {
989 : if( bVerbose )
990 : printf("INFO: %s: Creation of layer with geom_type = %s failed.\n",
991 : poDriver->GetDescription(),
992 : OGRGeometryTypeToName(eGeomType));
993 : }*/
994 624 : LOG_ACTION(GDALClose(poDS));
995 :
996 955 : if (eExpectedGeomType != wkbUnknown &&
997 : /* Those drivers are expected not to store a layer geometry type */
998 331 : !EQUAL(poDriver->GetDescription(), "KML") &&
999 316 : !EQUAL(poDriver->GetDescription(), "LIBKML") &&
1000 301 : !EQUAL(poDriver->GetDescription(), "PDF") &&
1001 286 : !EQUAL(poDriver->GetDescription(), "GeoJSON") &&
1002 271 : !EQUAL(poDriver->GetDescription(), "JSONFG") &&
1003 256 : !EQUAL(poDriver->GetDescription(), "OGR_GMT") &&
1004 1180 : !EQUAL(poDriver->GetDescription(), "PDS4") &&
1005 225 : !EQUAL(poDriver->GetDescription(), "FlatGeobuf"))
1006 : {
1007 : /* Reopen dataset */
1008 210 : poDS = LOG_ACTION(static_cast<GDALDataset *>(
1009 : GDALOpenEx(osFilename, GDAL_OF_VECTOR, nullptr, nullptr, nullptr)));
1010 210 : if (poDS != nullptr)
1011 : {
1012 175 : poLayer = LOG_ACTION(poDS->GetLayerByName(osLayerNameToTest));
1013 175 : if (poLayer != nullptr)
1014 : {
1015 114 : if (poLayer->GetGeomType() != eExpectedGeomType &&
1016 0 : !(eGeomType == wkbGeometryCollection25D &&
1017 0 : EQUAL(poDriver->GetDescription(), "OpenFileGDB")))
1018 : {
1019 0 : printf("ERROR: %s: GetGeomType() returns %d but %d "
1020 : "was expected (and %d originally set).\n",
1021 0 : poDriver->GetDescription(), poLayer->GetGeomType(),
1022 : eExpectedGeomType, eGeomType);
1023 0 : bRet = FALSE;
1024 : }
1025 : }
1026 175 : LOG_ACTION(GDALClose(poDS));
1027 : }
1028 : }
1029 :
1030 624 : CPLPushErrorHandler(CPLQuietErrorHandler);
1031 624 : LOG_ACTION(poDriver->Delete(osFilename));
1032 624 : CPLPopErrorHandler();
1033 624 : VSIUnlink(osFilename);
1034 :
1035 624 : if (poLayer != nullptr)
1036 : {
1037 : /* Test creating empty layer */
1038 : osFilename = CPLFormFilename("/vsimem",
1039 469 : CPLSPrintf("test%d", ++nCounter), pszExt);
1040 469 : poDS = LOG_ACTION(
1041 : poDriver->Create(osFilename, 0, 0, 0, GDT_Unknown, nullptr));
1042 469 : if (poDS != nullptr)
1043 : {
1044 469 : CPLPushErrorHandler(CPLQuietErrorHandler);
1045 469 : LOG_ACTION(poDS->CreateLayer(CPLGetFilename(osFilename), nullptr,
1046 : eGeomType));
1047 469 : CPLPopErrorHandler();
1048 469 : LOG_ACTION(GDALClose(poDS));
1049 :
1050 469 : CPLPushErrorHandler(CPLQuietErrorHandler);
1051 469 : LOG_ACTION(poDriver->Delete(osFilename));
1052 469 : CPLPopErrorHandler();
1053 469 : VSIUnlink(osFilename);
1054 : }
1055 : }
1056 :
1057 624 : return bRet;
1058 : }
1059 :
1060 : /************************************************************************/
1061 : /* TestCreate() */
1062 : /************************************************************************/
1063 :
1064 91 : static int TestCreate(GDALDriver *poDriver, int bFromAllDrivers)
1065 : {
1066 91 : int bRet = TRUE;
1067 : const bool bVirtualIO =
1068 91 : poDriver->GetMetadataItem(GDAL_DCAP_VIRTUALIO) != nullptr;
1069 91 : if (poDriver->GetMetadataItem(GDAL_DCAP_CREATE) == nullptr || !bVirtualIO)
1070 : {
1071 46 : if (bVerbose && !bFromAllDrivers)
1072 0 : printf("INFO: %s: TestCreate skipped.\n",
1073 0 : poDriver->GetDescription());
1074 46 : return TRUE;
1075 : }
1076 :
1077 45 : printf("%s\n", LOG_STR(CPLSPrintf("INFO: TestCreate(%s).",
1078 : poDriver->GetDescription())));
1079 :
1080 45 : const char *pszExt = poDriver->GetMetadataItem(GDAL_DMD_EXTENSION);
1081 45 : CPLString osFilename = CPLFormFilename("/foo", "test", pszExt);
1082 45 : CPLPushErrorHandler(CPLQuietErrorHandler);
1083 : GDALDataset *poDS =
1084 45 : LOG_ACTION(poDriver->Create(osFilename, 0, 0, 0, GDT_Unknown, nullptr));
1085 45 : CPLPopErrorHandler();
1086 45 : if (poDS != nullptr)
1087 : {
1088 : /* Sometimes actual file creation is deferred */
1089 9 : CPLPushErrorHandler(CPLQuietErrorHandler);
1090 : OGRLayer *poLayer =
1091 9 : LOG_ACTION(poDS->CreateLayer("test", nullptr, wkbPoint));
1092 9 : CPLPopErrorHandler();
1093 :
1094 : /* Or sometimes writing is deferred at dataset closing */
1095 9 : CPLErrorReset();
1096 9 : CPLPushErrorHandler(CPLQuietErrorHandler);
1097 9 : LOG_ACTION(GDALClose(poDS));
1098 9 : CPLPopErrorHandler();
1099 9 : if (poLayer != nullptr && CPLGetLastErrorType() == 0)
1100 : {
1101 2 : printf("INFO: %s: Creation of %s should have failed.\n",
1102 1 : poDriver->GetDescription(), osFilename.c_str());
1103 : }
1104 : }
1105 :
1106 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbUnknown));
1107 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbNone));
1108 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbPoint));
1109 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbLineString));
1110 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbPolygon));
1111 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiPoint));
1112 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiLineString));
1113 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiPolygon));
1114 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbGeometryCollection));
1115 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbPoint25D));
1116 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbLineString25D));
1117 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbPolygon25D));
1118 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiPoint25D));
1119 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiLineString25D));
1120 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbMultiPolygon25D));
1121 45 : bRet &= LOG_ACTION(TestCreateLayer(poDriver, wkbGeometryCollection25D));
1122 :
1123 45 : return bRet;
1124 : }
1125 :
1126 : /************************************************************************/
1127 : /* Usage() */
1128 : /************************************************************************/
1129 :
1130 0 : static void Usage()
1131 :
1132 : {
1133 0 : printf("Usage: test_ogrsf [-ro] [-q] [-threads N] [-loops M] [-fsf]\n"
1134 : " (datasource_name | [-driver driver_name] [[-dsco "
1135 : "NAME=VALUE] ...] [[-lco NAME=VALUE] ...] | -all_drivers) \n"
1136 : " [[layer1_name, layer2_name, ...] | [-sql "
1137 : "statement] [-dialect dialect]]\n"
1138 : " [[-oo NAME=VALUE] ...]\n");
1139 0 : printf("\n");
1140 0 : printf("-fsf : full spatial filter testing (slow)\n");
1141 0 : exit(1);
1142 : }
1143 :
1144 : /************************************************************************/
1145 : /* TestBasic() */
1146 : /************************************************************************/
1147 :
1148 302 : static int TestBasic(GDALDataset *poDS, OGRLayer *poLayer)
1149 : {
1150 302 : int bRet = TRUE;
1151 :
1152 302 : const char *pszLayerName = LOG_ACTION(poLayer->GetName());
1153 302 : const OGRwkbGeometryType eGeomType = LOG_ACTION(poLayer->GetGeomType());
1154 302 : OGRFeatureDefn *poFDefn = LOG_ACTION(poLayer->GetLayerDefn());
1155 :
1156 302 : if (strcmp(pszLayerName, LOG_ACTION(poFDefn->GetName())) != 0)
1157 : {
1158 0 : bRet = FALSE;
1159 0 : printf("ERROR: poLayer->GetName() and poFDefn->GetName() differ.\n"
1160 : "poLayer->GetName() = %s\n"
1161 : "poFDefn->GetName() = %s\n",
1162 0 : pszLayerName, poFDefn->GetName());
1163 : }
1164 :
1165 302 : if (strcmp(pszLayerName, LOG_ACTION(poLayer->GetDescription())) != 0)
1166 : {
1167 0 : bRet = FALSE;
1168 0 : printf(
1169 : "ERROR: poLayer->GetName() and poLayer->GetDescription() differ.\n"
1170 : "poLayer->GetName() = %s\n"
1171 : "poLayer->GetDescription() = %s\n",
1172 0 : pszLayerName, poLayer->GetDescription());
1173 : }
1174 :
1175 302 : if (eGeomType != LOG_ACTION(poFDefn->GetGeomType()))
1176 : {
1177 0 : bRet = FALSE;
1178 0 : printf(
1179 : "ERROR: poLayer->GetGeomType() and poFDefn->GetGeomType() differ.\n"
1180 : "poLayer->GetGeomType() = %d\n"
1181 : "poFDefn->GetGeomType() = %d\n",
1182 0 : eGeomType, poFDefn->GetGeomType());
1183 : }
1184 :
1185 302 : if (LOG_ACTION(poLayer->GetFIDColumn()) == nullptr)
1186 : {
1187 0 : bRet = FALSE;
1188 0 : printf("ERROR: poLayer->GetFIDColumn() returned NULL.\n");
1189 : }
1190 :
1191 302 : if (LOG_ACTION(poLayer->GetGeometryColumn()) == nullptr)
1192 : {
1193 0 : bRet = FALSE;
1194 0 : printf("ERROR: poLayer->GetGeometryColumn() returned NULL.\n");
1195 : }
1196 :
1197 302 : if (LOG_ACTION(poFDefn->GetGeomFieldCount()) > 0)
1198 : {
1199 228 : if (eGeomType != LOG_ACTION(poFDefn->GetGeomFieldDefn(0))->GetType())
1200 : {
1201 0 : bRet = FALSE;
1202 0 : printf("ERROR: poLayer->GetGeomType() and "
1203 : "poFDefn->GetGeomFieldDefn(0)->GetType() differ.\n"
1204 : "poLayer->GetGeomType() = %d\n"
1205 : "poFDefn->GetGeomFieldDefn(0)->GetType() = %d\n",
1206 0 : eGeomType, poFDefn->GetGeomFieldDefn(0)->GetType());
1207 : }
1208 :
1209 228 : if (!EQUAL(LOG_ACTION(poLayer->GetGeometryColumn()),
1210 : poFDefn->GetGeomFieldDefn(0)->GetNameRef()))
1211 : {
1212 0 : if (poFDefn->GetGeomFieldCount() > 1)
1213 0 : bRet = FALSE;
1214 0 : printf("%s: poLayer->GetGeometryColumn() and "
1215 : "poFDefn->GetGeomFieldDefn(0)->GetNameRef() differ.\n"
1216 : "poLayer->GetGeometryColumn() = %s\n"
1217 : "poFDefn->GetGeomFieldDefn(0)->GetNameRef() = %s\n",
1218 0 : (poFDefn->GetGeomFieldCount() == 1) ? "WARNING" : "ERROR",
1219 0 : poLayer->GetGeometryColumn(),
1220 0 : poFDefn->GetGeomFieldDefn(0)->GetNameRef());
1221 : }
1222 :
1223 228 : if (LOG_ACTION(poLayer->GetSpatialRef()) !=
1224 228 : LOG_ACTION(poFDefn->GetGeomFieldDefn(0)->GetSpatialRef()))
1225 : {
1226 1 : if (poFDefn->GetGeomFieldCount() > 1)
1227 0 : bRet = FALSE;
1228 1 : printf("%s: poLayer->GetSpatialRef() and "
1229 : "poFDefn->GetGeomFieldDefn(0)->GetSpatialRef() differ.\n"
1230 : "poLayer->GetSpatialRef() = %p\n"
1231 : "poFDefn->GetGeomFieldDefn(0)->GetSpatialRef() = %p\n",
1232 1 : (poFDefn->GetGeomFieldCount() == 1) ? "WARNING" : "ERROR",
1233 1 : poLayer->GetSpatialRef(),
1234 1 : poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
1235 : }
1236 : }
1237 :
1238 : // Test consistency of layer capabilities and driver metadata
1239 302 : if (poDS)
1240 : {
1241 302 : GDALDriver *poDriver = poDS->GetDriver();
1242 :
1243 302 : const bool bLayerShouldHaveEditCapabilities =
1244 302 : !bReadOnly && !pszSQLStatement;
1245 :
1246 : // metadata measure tests
1247 459 : if (poLayer->TestCapability(OLCMeasuredGeometries) &&
1248 157 : !poDriver->GetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES))
1249 : {
1250 0 : bRet = FALSE;
1251 0 : printf("FAILURE: Layer advertises OLCMeasuredGeometries capability "
1252 : "but driver metadata does not advertise "
1253 : "GDAL_DCAP_MEASURED_GEOMETRIES!\n");
1254 : }
1255 476 : if (poDS->TestCapability(ODsCMeasuredGeometries) &&
1256 174 : !poDriver->GetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES))
1257 : {
1258 0 : bRet = FALSE;
1259 0 : printf("FAILURE: Datasource advertises ODsCMeasuredGeometries "
1260 : "capability but driver metadata does not advertise "
1261 : "GDAL_DCAP_MEASURED_GEOMETRIES!\n");
1262 : }
1263 459 : if (poLayer->TestCapability(OLCMeasuredGeometries) &&
1264 157 : !poDS->TestCapability(ODsCMeasuredGeometries))
1265 : {
1266 0 : bRet = FALSE;
1267 0 : printf(
1268 : "FAILURE: Layer advertises OLCMeasuredGeometries capability "
1269 : "but datasource does not advertise ODsCMeasuredGeometries!\n");
1270 : }
1271 :
1272 : // metadata curve tests
1273 428 : if (poLayer->TestCapability(OLCCurveGeometries) &&
1274 126 : !poDriver->GetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES))
1275 : {
1276 0 : bRet = FALSE;
1277 0 : printf("FAILURE: Layer advertises OLCCurveGeometries capability "
1278 : "but driver metadata does not advertise "
1279 : "GDAL_DCAP_CURVE_GEOMETRIES!\n");
1280 : }
1281 438 : if (poDS->TestCapability(ODsCCurveGeometries) &&
1282 136 : !poDriver->GetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES))
1283 : {
1284 0 : bRet = FALSE;
1285 0 : printf("FAILURE: Datasource advertises ODsCCurveGeometries "
1286 : "capability but driver metadata does not advertise "
1287 : "GDAL_DCAP_CURVE_GEOMETRIES!\n");
1288 : }
1289 428 : if (poLayer->TestCapability(OLCCurveGeometries) &&
1290 126 : !poDS->TestCapability(ODsCCurveGeometries))
1291 : {
1292 0 : bRet = FALSE;
1293 0 : printf("FAILURE: Layer advertises OLCCurveGeometries capability "
1294 : "but datasource does not advertise ODsCCurveGeometries!\n");
1295 : }
1296 :
1297 : // metadata z dimension tests
1298 524 : if (poLayer->TestCapability(OLCZGeometries) &&
1299 222 : !poDriver->GetMetadataItem(GDAL_DCAP_Z_GEOMETRIES))
1300 : {
1301 0 : bRet = FALSE;
1302 0 : printf(
1303 : "FAILURE: Layer advertises OLCZGeometries capability but "
1304 : "driver metadata does not advertise GDAL_DCAP_Z_GEOMETRIES!\n");
1305 : }
1306 543 : if (poDS->TestCapability(ODsCZGeometries) &&
1307 241 : !poDriver->GetMetadataItem(GDAL_DCAP_Z_GEOMETRIES))
1308 : {
1309 0 : bRet = FALSE;
1310 0 : printf(
1311 : "FAILURE: Datasource advertises ODsCZGeometries capability but "
1312 : "driver metadata does not advertise GDAL_DCAP_Z_GEOMETRIES!\n");
1313 : }
1314 524 : if (poLayer->TestCapability(OLCZGeometries) &&
1315 222 : !poDS->TestCapability(ODsCZGeometries))
1316 : {
1317 0 : bRet = FALSE;
1318 0 : printf("FAILURE: Layer advertises OLCZGeometries capability but "
1319 : "datasource does not advertise ODsCZGeometries!\n");
1320 : }
1321 :
1322 : // note -- it's not safe to test the reverse case for these next two
1323 : // situations as some drivers only support CreateField() on newly
1324 : // created layers before the first feature is written
1325 334 : if (poLayer->TestCapability(OLCCreateField) &&
1326 32 : !poDriver->GetMetadataItem(GDAL_DCAP_CREATE_FIELD))
1327 : {
1328 0 : bRet = FALSE;
1329 0 : printf(
1330 : "FAILURE: Layer advertises OLCCreateField capability but "
1331 : "driver metadata does not advertise GDAL_DCAP_CREATE_FIELD!\n");
1332 : }
1333 334 : if (poLayer->TestCapability(OLCCreateField) &&
1334 32 : !poDriver->GetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES))
1335 : {
1336 0 : bRet = FALSE;
1337 0 : printf("FAILURE: Layer advertises OLCCreateField capability but "
1338 : "driver metadata does not include "
1339 : "GDAL_DMD_CREATIONFIELDDATATYPES!\n");
1340 : }
1341 :
1342 325 : if (poLayer->TestCapability(OLCDeleteField) &&
1343 23 : !poDriver->GetMetadataItem(GDAL_DCAP_DELETE_FIELD))
1344 : {
1345 0 : bRet = FALSE;
1346 0 : printf(
1347 : "FAILURE: Layer advertises OLCDeleteField capability but "
1348 : "driver metadata does not advertise GDAL_DCAP_DELETE_FIELD!\n");
1349 : }
1350 340 : if (bLayerShouldHaveEditCapabilities &&
1351 321 : poDriver->GetMetadataItem(GDAL_DCAP_DELETE_FIELD) &&
1352 19 : !poLayer->TestCapability(OLCDeleteField))
1353 : {
1354 0 : bRet = FALSE;
1355 0 : printf("FAILURE: Driver metadata advertises GDAL_DCAP_DELETE_FIELD "
1356 : "but layer capability does not advertise OLCDeleteField!\n");
1357 : }
1358 :
1359 318 : if (poLayer->TestCapability(OLCReorderFields) &&
1360 16 : !poDriver->GetMetadataItem(GDAL_DCAP_REORDER_FIELDS))
1361 : {
1362 0 : bRet = FALSE;
1363 0 : printf("FAILURE: Layer advertises OLCReorderFields capability but "
1364 : "driver metadata does not advertise "
1365 : "GDAL_DCAP_REORDER_FIELDS!\n");
1366 : }
1367 340 : if (bLayerShouldHaveEditCapabilities &&
1368 314 : poDriver->GetMetadataItem(GDAL_DCAP_REORDER_FIELDS) &&
1369 12 : !poLayer->TestCapability(OLCReorderFields))
1370 : {
1371 0 : bRet = FALSE;
1372 0 : printf(
1373 : "FAILURE: Driver metadata advertises GDAL_DCAP_REORDER_FIELDS "
1374 : "but layer capability does not advertise OLCReorderFields!\n");
1375 : }
1376 :
1377 324 : if (poLayer->TestCapability(OLCAlterFieldDefn) &&
1378 22 : !poDriver->GetMetadataItem(GDAL_DMD_ALTER_FIELD_DEFN_FLAGS))
1379 : {
1380 0 : bRet = FALSE;
1381 0 : printf("FAILURE: Layer advertises OLCAlterFieldDefn capability but "
1382 : "driver metadata does not include "
1383 : "GDAL_DMD_ALTER_FIELD_DEFN_FLAGS!\n");
1384 : }
1385 340 : if (bLayerShouldHaveEditCapabilities &&
1386 320 : poDriver->GetMetadataItem(GDAL_DMD_ALTER_FIELD_DEFN_FLAGS) &&
1387 18 : !poLayer->TestCapability(OLCAlterFieldDefn))
1388 : {
1389 0 : bRet = FALSE;
1390 0 : printf("FAILURE: Driver metadata advertises "
1391 : "GDAL_DMD_ALTER_FIELD_DEFN_FLAGS but layer capability does "
1392 : "not advertise OLCAlterFieldDefn!\n");
1393 : }
1394 : }
1395 :
1396 302 : return bRet;
1397 : }
1398 :
1399 : /************************************************************************/
1400 : /* TestLayerErrorConditions() */
1401 : /************************************************************************/
1402 :
1403 302 : static int TestLayerErrorConditions(OGRLayer *poLyr)
1404 : {
1405 302 : int bRet = TRUE;
1406 302 : OGRFeature *poFeat = nullptr;
1407 :
1408 302 : CPLPushErrorHandler(CPLQuietErrorHandler);
1409 :
1410 302 : if (LOG_ACTION(poLyr->TestCapability("fake_capability")))
1411 : {
1412 0 : printf("ERROR: poLyr->TestCapability(\"fake_capability\") "
1413 : "should have returned FALSE\n");
1414 0 : bRet = FALSE;
1415 0 : goto bye;
1416 : }
1417 :
1418 302 : if (LOG_ACTION(poLyr->GetFeature(-10)) != nullptr)
1419 : {
1420 0 : printf("ERROR: GetFeature(-10) should have returned NULL\n");
1421 0 : bRet = FALSE;
1422 0 : goto bye;
1423 : }
1424 :
1425 302 : if (LOG_ACTION(poLyr->GetFeature(2000000000)) != nullptr)
1426 : {
1427 0 : printf("ERROR: GetFeature(2000000000) should have returned NULL\n");
1428 0 : bRet = FALSE;
1429 0 : goto bye;
1430 : }
1431 :
1432 : // This should detect int overflow
1433 302 : if (LOG_ACTION(poLyr->GetFeature(
1434 302 : static_cast<GIntBig>(std::numeric_limits<int>::max()) + 1)) !=
1435 : nullptr)
1436 : {
1437 0 : printf("ERROR: GetFeature((GIntBig)INT_MAX + 1) "
1438 : "should have returned NULL\n");
1439 0 : bRet = FALSE;
1440 0 : goto bye;
1441 : }
1442 :
1443 302 : poLyr->ResetReading();
1444 302 : poFeat = poLyr->GetNextFeature();
1445 302 : if (poFeat)
1446 : {
1447 283 : poFeat->SetFID(-10);
1448 283 : if (poLyr->SetFeature(poFeat) == OGRERR_NONE)
1449 : {
1450 0 : printf("ERROR: SetFeature(-10) should have returned an error\n");
1451 0 : delete poFeat;
1452 0 : bRet = FALSE;
1453 0 : goto bye;
1454 : }
1455 283 : delete poFeat;
1456 : }
1457 :
1458 302 : if (poLyr->DeleteFeature(-10) == OGRERR_NONE)
1459 : {
1460 0 : printf("ERROR: DeleteFeature(-10) should have returned an error\n");
1461 0 : bRet = FALSE;
1462 0 : goto bye;
1463 : }
1464 :
1465 302 : if (poLyr->DeleteFeature(2000000000) == OGRERR_NONE)
1466 : {
1467 0 : printf("ERROR: DeleteFeature(2000000000) should have "
1468 : "returned an error\n");
1469 0 : bRet = FALSE;
1470 0 : goto bye;
1471 : }
1472 :
1473 302 : if (LOG_ACTION(poLyr->SetNextByIndex(-10)) != OGRERR_FAILURE)
1474 : {
1475 0 : printf("ERROR: SetNextByIndex(-10) should have "
1476 : "returned OGRERR_FAILURE\n");
1477 0 : bRet = FALSE;
1478 0 : goto bye;
1479 : }
1480 :
1481 311 : if (LOG_ACTION(poLyr->SetNextByIndex(2000000000)) == OGRERR_NONE &&
1482 9 : LOG_ACTION(poLyr->GetNextFeature()) != nullptr)
1483 : {
1484 0 : printf("ERROR: SetNextByIndex(2000000000) and then GetNextFeature() "
1485 : "should have returned NULL\n");
1486 0 : bRet = FALSE;
1487 0 : goto bye;
1488 : }
1489 :
1490 302 : bye:
1491 302 : CPLPopErrorHandler();
1492 302 : return bRet;
1493 : }
1494 :
1495 : /************************************************************************/
1496 : /* GetLayerNameForSQL() */
1497 : /************************************************************************/
1498 :
1499 1168 : static const char *GetLayerNameForSQL(GDALDataset *poDS,
1500 : const char *pszLayerName)
1501 : {
1502 : char ch;
1503 9328 : for (int i = 0; (ch = pszLayerName[i]) != 0; i++)
1504 : {
1505 8588 : if (ch >= '0' && ch <= '9')
1506 : {
1507 308 : if (i == 0)
1508 0 : break;
1509 : }
1510 8280 : else if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
1511 : break;
1512 : }
1513 : /* Only quote if needed. Quoting conventions depend on the driver... */
1514 1168 : if (ch == 0)
1515 740 : return pszLayerName;
1516 :
1517 428 : if (EQUAL(poDS->GetDriverName(), "MYSQL"))
1518 0 : return CPLSPrintf("`%s`", pszLayerName);
1519 :
1520 428 : if (EQUAL(poDS->GetDriverName(), "PostgreSQL") && strchr(pszLayerName, '.'))
1521 : {
1522 0 : const char *pszRet = nullptr;
1523 0 : char **papszTokens = CSLTokenizeStringComplex(pszLayerName, ".", 0, 0);
1524 0 : if (CSLCount(papszTokens) == 2)
1525 : pszRet =
1526 0 : CPLSPrintf("\"%s\".\"%s\"", papszTokens[0], papszTokens[1]);
1527 : else
1528 0 : pszRet = CPLSPrintf("\"%s\"", pszLayerName);
1529 0 : CSLDestroy(papszTokens);
1530 0 : return pszRet;
1531 : }
1532 :
1533 428 : if (EQUAL(poDS->GetDriverName(), "SQLAnywhere"))
1534 0 : return pszLayerName;
1535 :
1536 428 : if (EQUAL(poDS->GetDriverName(), "DB2ODBC"))
1537 0 : return pszLayerName;
1538 :
1539 428 : return CPLSPrintf("\"%s\"", pszLayerName);
1540 : }
1541 :
1542 : /************************************************************************/
1543 : /* TestOGRLayerFeatureCount() */
1544 : /* */
1545 : /* Verify that the feature count matches the actual number of */
1546 : /* features returned during sequential reading. */
1547 : /************************************************************************/
1548 :
1549 302 : static int TestOGRLayerFeatureCount(GDALDataset *poDS, OGRLayer *poLayer,
1550 : int bIsSQLLayer)
1551 :
1552 : {
1553 302 : int bRet = TRUE;
1554 302 : GIntBig nFC = 0;
1555 302 : GIntBig nClaimedFC = LOG_ACTION(poLayer->GetFeatureCount());
1556 302 : bool bWarnAboutSRS = false;
1557 302 : OGRFeatureDefn *poLayerDefn = LOG_ACTION(poLayer->GetLayerDefn());
1558 302 : int nGeomFieldCount = LOG_ACTION(poLayerDefn->GetGeomFieldCount());
1559 :
1560 : const bool bLayerHasMeasuredGeometriesCapability =
1561 302 : poLayer->TestCapability(ODsCMeasuredGeometries);
1562 : const bool bLayerHasCurveGeometriesCapability =
1563 302 : poLayer->TestCapability(OLCCurveGeometries);
1564 : const bool bLayerHasZGeometriesCapability =
1565 302 : poLayer->TestCapability(OLCZGeometries);
1566 :
1567 302 : CPLErrorReset();
1568 :
1569 4077 : for (auto &&poFeature : poLayer)
1570 : {
1571 3775 : nFC++;
1572 :
1573 3775 : if (poFeature->GetDefnRef() != poLayerDefn)
1574 : {
1575 0 : bRet = FALSE;
1576 0 : printf("ERROR: Feature defn differs from layer defn.\n"
1577 : "Feature defn = %p\n"
1578 : "Layer defn = %p\n",
1579 : poFeature->GetDefnRef(), poLayerDefn);
1580 : }
1581 :
1582 6263 : for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
1583 : {
1584 2488 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeom);
1585 :
1586 2500 : if (poGeom && poGeom->IsMeasured() &&
1587 12 : !bLayerHasMeasuredGeometriesCapability)
1588 : {
1589 0 : bRet = FALSE;
1590 0 : printf("FAILURE: Layer has a feature with measured geometries "
1591 : "but no ODsCMeasuredGeometries capability!\n");
1592 : }
1593 2488 : if (poGeom && poGeom->hasCurveGeometry() &&
1594 0 : !bLayerHasCurveGeometriesCapability)
1595 : {
1596 0 : bRet = FALSE;
1597 0 : printf("FAILURE: Layer has a feature with curved geometries "
1598 : "but no OLCCurveGeometries capability!\n");
1599 : }
1600 2488 : if (poGeom && poGeom->Is3D() && !bLayerHasZGeometriesCapability)
1601 : {
1602 0 : bRet = FALSE;
1603 0 : printf("FAILURE: Layer has a feature with 3D geometries but no "
1604 : "OLCZGeometries capability!\n");
1605 : }
1606 :
1607 : const OGRSpatialReference *poGFldSRS =
1608 2488 : poLayerDefn->GetGeomFieldDefn(iGeom)->GetSpatialRef();
1609 :
1610 : // Compatibility with old drivers anterior to RFC 41
1611 2488 : if (iGeom == 0 && nGeomFieldCount == 1 && poGFldSRS == nullptr)
1612 935 : poGFldSRS = poLayer->GetSpatialRef();
1613 :
1614 2370 : if (poGeom != nullptr &&
1615 4858 : poGeom->getSpatialReference() != poGFldSRS && !bWarnAboutSRS)
1616 : {
1617 0 : bWarnAboutSRS = true;
1618 :
1619 0 : char *pszLayerSRSWKT = nullptr;
1620 0 : if (poGFldSRS != nullptr)
1621 0 : poGFldSRS->exportToWkt(&pszLayerSRSWKT);
1622 : else
1623 0 : pszLayerSRSWKT = CPLStrdup("(NULL)");
1624 :
1625 0 : char *pszFeatureSRSWKT = nullptr;
1626 0 : if (poGeom->getSpatialReference() != nullptr)
1627 0 : poGeom->getSpatialReference()->exportToWkt(
1628 : &pszFeatureSRSWKT);
1629 : else
1630 0 : pszFeatureSRSWKT = CPLStrdup("(NULL)");
1631 :
1632 0 : bRet = FALSE;
1633 0 : printf("ERROR: Feature SRS differs from layer SRS.\n"
1634 : "Feature SRS = %s (%p)\n"
1635 : "Layer SRS = %s (%p)\n",
1636 : pszFeatureSRSWKT, poGeom->getSpatialReference(),
1637 : pszLayerSRSWKT, poGFldSRS);
1638 0 : CPLFree(pszLayerSRSWKT);
1639 0 : CPLFree(pszFeatureSRSWKT);
1640 : }
1641 : }
1642 : }
1643 :
1644 : /* mapogr.cpp doesn't like errors after GetNextFeature() */
1645 302 : if (CPLGetLastErrorType() == CE_Failure)
1646 : {
1647 0 : bRet = FALSE;
1648 0 : printf("ERROR: An error was reported : %s\n", CPLGetLastErrorMsg());
1649 : }
1650 :
1651 : // Drivers might or might not emit errors when attempting to iterate
1652 : // after EOF
1653 302 : CPLPushErrorHandler(CPLQuietErrorHandler);
1654 302 : auto poFeat = LOG_ACTION(poLayer->GetNextFeature());
1655 302 : CPLPopErrorHandler();
1656 302 : if (poFeat != nullptr)
1657 : {
1658 0 : bRet = FALSE;
1659 0 : printf("ERROR: GetNextFeature() returned non NULL feature after end of "
1660 : "iteration.\n");
1661 : }
1662 302 : delete poFeat;
1663 :
1664 302 : if (nFC != nClaimedFC)
1665 : {
1666 0 : bRet = FALSE;
1667 0 : printf("ERROR: Claimed feature count " CPL_FRMT_GIB
1668 : " doesn't match actual, " CPL_FRMT_GIB ".\n",
1669 : nClaimedFC, nFC);
1670 : }
1671 302 : else if (nFC != LOG_ACTION(poLayer->GetFeatureCount()))
1672 : {
1673 0 : bRet = FALSE;
1674 0 : printf("ERROR: Feature count at end of layer, " CPL_FRMT_GIB
1675 : ", differs from at start, " CPL_FRMT_GIB ".\n",
1676 0 : poLayer->GetFeatureCount(), nFC);
1677 : }
1678 302 : else if (bVerbose)
1679 302 : printf("INFO: Feature count verified.\n");
1680 :
1681 302 : if (!bIsSQLLayer)
1682 : {
1683 584 : CPLString osSQL;
1684 :
1685 : osSQL.Printf("SELECT COUNT(*) FROM %s",
1686 292 : GetLayerNameForSQL(poDS, poLayer->GetName()));
1687 :
1688 292 : OGRLayer *poSQLLyr = poDS->ExecuteSQL(osSQL.c_str(), nullptr, nullptr);
1689 292 : if (poSQLLyr)
1690 : {
1691 292 : OGRFeature *poFeatCount = poSQLLyr->GetNextFeature();
1692 292 : if (poFeatCount == nullptr)
1693 : {
1694 0 : bRet = FALSE;
1695 0 : printf("ERROR: '%s' failed.\n", osSQL.c_str());
1696 : }
1697 292 : else if (nClaimedFC != poFeatCount->GetFieldAsInteger(0))
1698 : {
1699 0 : bRet = FALSE;
1700 0 : printf("ERROR: Claimed feature count " CPL_FRMT_GIB
1701 : " doesn't match '%s' one, " CPL_FRMT_GIB ".\n",
1702 : nClaimedFC, osSQL.c_str(),
1703 : poFeatCount->GetFieldAsInteger64(0));
1704 : }
1705 292 : DestroyFeatureAndNullify(poFeatCount);
1706 292 : poDS->ReleaseResultSet(poSQLLyr);
1707 : }
1708 : }
1709 :
1710 302 : if (bVerbose && !bWarnAboutSRS)
1711 : {
1712 302 : printf("INFO: Feature/layer spatial ref. consistency verified.\n");
1713 : }
1714 :
1715 302 : return bRet;
1716 : }
1717 :
1718 : /************************************************************************/
1719 : /* TestOGRLayerRandomRead() */
1720 : /* */
1721 : /* Read the first 5 features, and then try to use random */
1722 : /* reading to reread 2 and 5 and verify that this works OK. */
1723 : /* Don't attempt if there aren't at least 5 features. */
1724 : /************************************************************************/
1725 :
1726 302 : static int TestOGRLayerRandomRead(OGRLayer *poLayer)
1727 :
1728 : {
1729 302 : int bRet = TRUE;
1730 302 : OGRFeature *papoFeatures[5], *poFeature = nullptr;
1731 :
1732 302 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
1733 :
1734 302 : if (LOG_ACTION(poLayer->GetFeatureCount()) < 5)
1735 : {
1736 147 : if (bVerbose)
1737 147 : printf("INFO: Only " CPL_FRMT_GIB " features on layer,"
1738 : "skipping random read test.\n",
1739 147 : poLayer->GetFeatureCount());
1740 :
1741 147 : return bRet;
1742 : }
1743 :
1744 : /* -------------------------------------------------------------------- */
1745 : /* Fetch five features. */
1746 : /* -------------------------------------------------------------------- */
1747 155 : LOG_ACTION(poLayer->ResetReading());
1748 :
1749 930 : for (int iFeature = 0; iFeature < 5; iFeature++)
1750 : {
1751 775 : papoFeatures[iFeature] = nullptr;
1752 : }
1753 930 : for (int iFeature = 0; iFeature < 5; iFeature++)
1754 : {
1755 775 : papoFeatures[iFeature] = LOG_ACTION(poLayer->GetNextFeature());
1756 775 : if (papoFeatures[iFeature] == nullptr)
1757 : {
1758 0 : if (bVerbose)
1759 0 : printf("INFO: Only %d features on layer,"
1760 : "skipping random read test.\n",
1761 : iFeature);
1762 0 : goto end;
1763 : }
1764 : }
1765 :
1766 : /* -------------------------------------------------------------------- */
1767 : /* Test feature 2. */
1768 : /* -------------------------------------------------------------------- */
1769 155 : poFeature = LOG_ACTION(poLayer->GetFeature(papoFeatures[1]->GetFID()));
1770 155 : if (poFeature == nullptr)
1771 : {
1772 0 : printf("ERROR: Cannot fetch feature " CPL_FRMT_GIB ".\n",
1773 0 : papoFeatures[1]->GetFID());
1774 0 : goto end;
1775 : }
1776 :
1777 155 : if (!poFeature->Equal(papoFeatures[1]))
1778 : {
1779 0 : bRet = FALSE;
1780 0 : printf("ERROR: Attempt to randomly read feature " CPL_FRMT_GIB
1781 : " appears to\n"
1782 : " have returned a different feature than sequential\n"
1783 : " reading indicates should have happened.\n",
1784 0 : papoFeatures[1]->GetFID());
1785 0 : poFeature->DumpReadable(stdout);
1786 0 : papoFeatures[1]->DumpReadable(stdout);
1787 :
1788 0 : goto end;
1789 : }
1790 :
1791 155 : DestroyFeatureAndNullify(poFeature);
1792 :
1793 : /* -------------------------------------------------------------------- */
1794 : /* Test feature 5. */
1795 : /* -------------------------------------------------------------------- */
1796 155 : poFeature = LOG_ACTION(poLayer->GetFeature(papoFeatures[4]->GetFID()));
1797 155 : if (poFeature == nullptr)
1798 : {
1799 0 : printf("ERROR: Cannot fetch feature " CPL_FRMT_GIB ".\n",
1800 0 : papoFeatures[4]->GetFID());
1801 0 : goto end;
1802 : }
1803 :
1804 155 : if (!poFeature->Equal(papoFeatures[4]))
1805 : {
1806 0 : bRet = FALSE;
1807 0 : printf("ERROR: Attempt to randomly read feature " CPL_FRMT_GIB
1808 : " appears to\n"
1809 : " have returned a different feature than sequential\n"
1810 : " reading indicates should have happened.\n",
1811 0 : papoFeatures[4]->GetFID());
1812 0 : poFeature->DumpReadable(stdout);
1813 0 : papoFeatures[4]->DumpReadable(stdout);
1814 :
1815 0 : goto end;
1816 : }
1817 :
1818 155 : DestroyFeatureAndNullify(poFeature);
1819 :
1820 : /* -------------------------------------------------------------------- */
1821 : /* Test feature 2 again */
1822 : /* -------------------------------------------------------------------- */
1823 155 : poFeature = LOG_ACTION(poLayer->GetFeature(papoFeatures[2]->GetFID()));
1824 155 : if (poFeature == nullptr)
1825 : {
1826 0 : printf("ERROR: Cannot fetch feature " CPL_FRMT_GIB ".\n",
1827 0 : papoFeatures[2]->GetFID());
1828 0 : goto end;
1829 : }
1830 :
1831 155 : if (!poFeature->Equal(papoFeatures[2]))
1832 : {
1833 0 : bRet = FALSE;
1834 0 : printf("ERROR: Attempt to randomly read feature " CPL_FRMT_GIB
1835 : " appears to\n"
1836 : " have returned a different feature than sequential\n"
1837 : " reading indicates should have happened.\n",
1838 0 : papoFeatures[2]->GetFID());
1839 0 : poFeature->DumpReadable(stdout);
1840 0 : papoFeatures[2]->DumpReadable(stdout);
1841 :
1842 0 : goto end;
1843 : }
1844 :
1845 155 : if (bVerbose)
1846 155 : printf("INFO: Random read test passed.\n");
1847 :
1848 0 : end:
1849 155 : DestroyFeatureAndNullify(poFeature);
1850 :
1851 : /* -------------------------------------------------------------------- */
1852 : /* Cleanup. */
1853 : /* -------------------------------------------------------------------- */
1854 930 : for (int iFeature = 0; iFeature < 5; iFeature++)
1855 775 : DestroyFeatureAndNullify(papoFeatures[iFeature]);
1856 :
1857 155 : return bRet;
1858 : }
1859 :
1860 : /************************************************************************/
1861 : /* TestOGRLayerSetNextByIndex() */
1862 : /* */
1863 : /************************************************************************/
1864 :
1865 302 : static int TestOGRLayerSetNextByIndex(OGRLayer *poLayer)
1866 :
1867 : {
1868 302 : int bRet = TRUE;
1869 302 : OGRFeature *poFeature = nullptr;
1870 : OGRFeature *papoFeatures[5];
1871 :
1872 302 : memset(papoFeatures, 0, sizeof(papoFeatures));
1873 :
1874 302 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
1875 :
1876 302 : if (LOG_ACTION(poLayer->GetFeatureCount()) < 5)
1877 : {
1878 147 : if (bVerbose)
1879 147 : printf("INFO: Only " CPL_FRMT_GIB " features on layer,"
1880 : "skipping SetNextByIndex test.\n",
1881 147 : poLayer->GetFeatureCount());
1882 :
1883 147 : return bRet;
1884 : }
1885 :
1886 : /* -------------------------------------------------------------------- */
1887 : /* Fetch five features. */
1888 : /* -------------------------------------------------------------------- */
1889 155 : LOG_ACTION(poLayer->ResetReading());
1890 :
1891 930 : for (int iFeature = 0; iFeature < 5; iFeature++)
1892 : {
1893 775 : papoFeatures[iFeature] = LOG_ACTION(poLayer->GetNextFeature());
1894 775 : if (papoFeatures[iFeature] == nullptr)
1895 : {
1896 0 : bRet = FALSE;
1897 0 : printf("ERROR: Cannot get feature %d.\n", iFeature);
1898 0 : goto end;
1899 : }
1900 : }
1901 :
1902 : /* -------------------------------------------------------------------- */
1903 : /* Test feature at index 1. */
1904 : /* -------------------------------------------------------------------- */
1905 155 : if (LOG_ACTION(poLayer->SetNextByIndex(1)) != OGRERR_NONE)
1906 : {
1907 0 : bRet = FALSE;
1908 0 : printf("ERROR: SetNextByIndex(%d) failed.\n", 1);
1909 0 : goto end;
1910 : }
1911 :
1912 155 : poFeature = LOG_ACTION(poLayer->GetNextFeature());
1913 155 : if (poFeature == nullptr || !poFeature->Equal(papoFeatures[1]))
1914 : {
1915 0 : bRet = FALSE;
1916 0 : printf("ERROR: Attempt to read feature at index %d appears to\n"
1917 : " have returned a different feature than sequential\n"
1918 : " reading indicates should have happened.\n",
1919 : 1);
1920 :
1921 0 : goto end;
1922 : }
1923 :
1924 155 : DestroyFeatureAndNullify(poFeature);
1925 :
1926 155 : poFeature = LOG_ACTION(poLayer->GetNextFeature());
1927 155 : if (poFeature == nullptr || !poFeature->Equal(papoFeatures[2]))
1928 : {
1929 0 : bRet = FALSE;
1930 0 : printf("ERROR: Attempt to read feature after feature at index %d "
1931 : "appears to\n"
1932 : " have returned a different feature than sequential\n"
1933 : " reading indicates should have happened.\n",
1934 : 1);
1935 :
1936 0 : goto end;
1937 : }
1938 :
1939 155 : DestroyFeatureAndNullify(poFeature);
1940 :
1941 : /* -------------------------------------------------------------------- */
1942 : /* Test feature at index 3. */
1943 : /* -------------------------------------------------------------------- */
1944 155 : if (LOG_ACTION(poLayer->SetNextByIndex(3)) != OGRERR_NONE)
1945 : {
1946 0 : bRet = FALSE;
1947 0 : printf("ERROR: SetNextByIndex(%d) failed.\n", 3);
1948 0 : goto end;
1949 : }
1950 :
1951 155 : poFeature = LOG_ACTION(poLayer->GetNextFeature());
1952 155 : if (!poFeature->Equal(papoFeatures[3]))
1953 : {
1954 0 : bRet = FALSE;
1955 0 : printf("ERROR: Attempt to read feature at index %d appears to\n"
1956 : " have returned a different feature than sequential\n"
1957 : " reading indicates should have happened.\n",
1958 : 3);
1959 :
1960 0 : goto end;
1961 : }
1962 :
1963 155 : DestroyFeatureAndNullify(poFeature);
1964 :
1965 155 : poFeature = LOG_ACTION(poLayer->GetNextFeature());
1966 155 : if (!poFeature->Equal(papoFeatures[4]))
1967 : {
1968 0 : bRet = FALSE;
1969 0 : printf("ERROR: Attempt to read feature after feature at index %d "
1970 : "appears to\n"
1971 : " have returned a different feature than sequential\n"
1972 : " reading indicates should have happened.\n",
1973 : 3);
1974 :
1975 0 : goto end;
1976 : }
1977 :
1978 155 : if (bVerbose)
1979 155 : printf("INFO: SetNextByIndex() read test passed.\n");
1980 :
1981 0 : end:
1982 155 : DestroyFeatureAndNullify(poFeature);
1983 :
1984 : /* -------------------------------------------------------------------- */
1985 : /* Cleanup. */
1986 : /* -------------------------------------------------------------------- */
1987 930 : for (int iFeature = 0; iFeature < 5; iFeature++)
1988 775 : DestroyFeatureAndNullify(papoFeatures[iFeature]);
1989 :
1990 155 : return bRet;
1991 : }
1992 :
1993 : /************************************************************************/
1994 : /* TestOGRLayerRandomWrite() */
1995 : /* */
1996 : /* Test random writing by trying to switch the 2nd and 5th */
1997 : /* features. */
1998 : /************************************************************************/
1999 :
2000 31 : static int TestOGRLayerRandomWrite(OGRLayer *poLayer)
2001 :
2002 : {
2003 31 : int bRet = TRUE;
2004 : OGRFeature *papoFeatures[5], *poFeature;
2005 :
2006 31 : memset(papoFeatures, 0, sizeof(papoFeatures));
2007 :
2008 31 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
2009 :
2010 31 : if (LOG_ACTION(poLayer->GetFeatureCount()) < 5)
2011 : {
2012 12 : if (bVerbose)
2013 12 : printf("INFO: Only " CPL_FRMT_GIB " features on layer,"
2014 : "skipping random write test.\n",
2015 12 : poLayer->GetFeatureCount());
2016 :
2017 12 : return bRet;
2018 : }
2019 :
2020 19 : if (!LOG_ACTION(poLayer->TestCapability(OLCRandomRead)))
2021 : {
2022 0 : if (bVerbose)
2023 0 : printf("INFO: Skipping random write test since this layer "
2024 : "doesn't support random read.\n");
2025 0 : return bRet;
2026 : }
2027 :
2028 : GIntBig nFID2;
2029 : GIntBig nFID5;
2030 :
2031 38 : CPLString os_Id2;
2032 19 : CPLString os_Id5;
2033 :
2034 19 : const bool bHas_Id = poLayer->GetLayerDefn()->GetFieldIndex("_id") == 0;
2035 :
2036 : /* -------------------------------------------------------------------- */
2037 : /* Fetch five features. */
2038 : /* -------------------------------------------------------------------- */
2039 19 : LOG_ACTION(poLayer->ResetReading());
2040 :
2041 114 : for (int iFeature = 0; iFeature < 5; iFeature++)
2042 : {
2043 95 : papoFeatures[iFeature] = LOG_ACTION(poLayer->GetNextFeature());
2044 95 : if (papoFeatures[iFeature] == nullptr)
2045 : {
2046 0 : bRet = FALSE;
2047 0 : printf("ERROR: Cannot get feature %d.\n", iFeature);
2048 0 : goto end;
2049 : }
2050 : }
2051 :
2052 : /* -------------------------------------------------------------------- */
2053 : /* Switch feature ids of feature 2 and 5. */
2054 : /* -------------------------------------------------------------------- */
2055 19 : nFID2 = papoFeatures[1]->GetFID();
2056 19 : nFID5 = papoFeatures[4]->GetFID();
2057 :
2058 19 : papoFeatures[1]->SetFID(nFID5);
2059 19 : papoFeatures[4]->SetFID(nFID2);
2060 :
2061 19 : if (bHas_Id)
2062 : {
2063 0 : os_Id2 = papoFeatures[1]->GetFieldAsString(0);
2064 0 : os_Id5 = papoFeatures[4]->GetFieldAsString(0);
2065 :
2066 0 : papoFeatures[1]->SetField(0, os_Id5);
2067 0 : papoFeatures[4]->SetField(0, os_Id2);
2068 : }
2069 :
2070 : /* -------------------------------------------------------------------- */
2071 : /* Rewrite them. */
2072 : /* -------------------------------------------------------------------- */
2073 19 : if (LOG_ACTION(poLayer->SetFeature(papoFeatures[1])) != OGRERR_NONE)
2074 : {
2075 0 : bRet = FALSE;
2076 0 : printf("ERROR: Attempt to SetFeature(1) failed.\n");
2077 0 : goto end;
2078 : }
2079 19 : if (LOG_ACTION(poLayer->SetFeature(papoFeatures[4])) != OGRERR_NONE)
2080 : {
2081 0 : bRet = FALSE;
2082 0 : printf("ERROR: Attempt to SetFeature(4) failed.\n");
2083 0 : goto end;
2084 : }
2085 :
2086 : /* -------------------------------------------------------------------- */
2087 : /* Now re-read feature 2 to verify the effect stuck. */
2088 : /* -------------------------------------------------------------------- */
2089 19 : poFeature = LOG_ACTION(poLayer->GetFeature(nFID5));
2090 19 : if (poFeature == nullptr)
2091 : {
2092 0 : bRet = FALSE;
2093 0 : printf("ERROR: Attempt to GetFeature( nFID5 ) failed.\n");
2094 0 : goto end;
2095 : }
2096 19 : if (!poFeature->Equal(papoFeatures[1]))
2097 : {
2098 0 : bRet = FALSE;
2099 0 : poFeature->DumpReadable(stderr);
2100 0 : papoFeatures[1]->DumpReadable(stderr);
2101 0 : printf("ERROR: Written feature didn't seem to retain value.\n");
2102 : }
2103 19 : else if (bVerbose)
2104 : {
2105 19 : printf("INFO: Random write test passed.\n");
2106 : }
2107 19 : DestroyFeatureAndNullify(poFeature);
2108 :
2109 : /* -------------------------------------------------------------------- */
2110 : /* Re-invert the features to restore to original state */
2111 : /* -------------------------------------------------------------------- */
2112 :
2113 19 : papoFeatures[1]->SetFID(nFID2);
2114 19 : papoFeatures[4]->SetFID(nFID5);
2115 :
2116 19 : if (bHas_Id)
2117 : {
2118 0 : papoFeatures[1]->SetField(0, os_Id2);
2119 0 : papoFeatures[4]->SetField(0, os_Id5);
2120 : }
2121 :
2122 19 : if (LOG_ACTION(poLayer->SetFeature(papoFeatures[1])) != OGRERR_NONE)
2123 : {
2124 0 : bRet = FALSE;
2125 0 : printf("ERROR: Attempt to restore SetFeature(1) failed.\n");
2126 : }
2127 19 : if (LOG_ACTION(poLayer->SetFeature(papoFeatures[4])) != OGRERR_NONE)
2128 : {
2129 0 : bRet = FALSE;
2130 0 : printf("ERROR: Attempt to restore SetFeature(4) failed.\n");
2131 : }
2132 :
2133 19 : end:
2134 : /* -------------------------------------------------------------------- */
2135 : /* Cleanup. */
2136 : /* -------------------------------------------------------------------- */
2137 :
2138 114 : for (int iFeature = 0; iFeature < 5; iFeature++)
2139 95 : DestroyFeatureAndNullify(papoFeatures[iFeature]);
2140 :
2141 19 : return bRet;
2142 : }
2143 :
2144 : /************************************************************************/
2145 : /* TestSpatialFilter() */
2146 : /* */
2147 : /* This is intended to be a simple test of the spatial */
2148 : /* filtering. We read the first feature. Then construct a */
2149 : /* spatial filter geometry which includes it, install and */
2150 : /* verify that we get the feature. Next install a spatial */
2151 : /* filter that doesn't include this feature, and test again. */
2152 : /************************************************************************/
2153 :
2154 233 : static int TestSpatialFilter(OGRLayer *poLayer, int iGeomField)
2155 :
2156 : {
2157 233 : int bRet = TRUE;
2158 :
2159 : /* -------------------------------------------------------------------- */
2160 : /* Read the target feature. */
2161 : /* -------------------------------------------------------------------- */
2162 233 : LOG_ACTION(poLayer->ResetReading());
2163 233 : OGRFeature *poTargetFeature = LOG_ACTION(poLayer->GetNextFeature());
2164 :
2165 233 : if (poTargetFeature == nullptr)
2166 : {
2167 0 : if (bVerbose)
2168 : {
2169 0 : printf("INFO: Skipping Spatial Filter test for %s.\n"
2170 : " No features in layer.\n",
2171 0 : poLayer->GetName());
2172 : }
2173 0 : return bRet;
2174 : }
2175 :
2176 233 : OGRGeometry *poGeom = poTargetFeature->GetGeomFieldRef(iGeomField);
2177 233 : if (poGeom == nullptr || poGeom->IsEmpty())
2178 : {
2179 22 : if (bVerbose)
2180 : {
2181 22 : printf("INFO: Skipping Spatial Filter test for %s,\n"
2182 : " target feature has no geometry.\n",
2183 22 : poTargetFeature->GetDefnRef()->GetName());
2184 : }
2185 22 : DestroyFeatureAndNullify(poTargetFeature);
2186 22 : return bRet;
2187 : }
2188 :
2189 211 : OGREnvelope sEnvelope;
2190 211 : poGeom->getEnvelope(&sEnvelope);
2191 :
2192 211 : OGREnvelope sLayerExtent;
2193 211 : double epsilon = 10.0;
2194 211 : if (LOG_ACTION(poLayer->TestCapability(OLCFastGetExtent)) &&
2195 136 : LOG_ACTION(poLayer->GetExtent(iGeomField, &sLayerExtent)) ==
2196 122 : OGRERR_NONE &&
2197 456 : sLayerExtent.MinX < sLayerExtent.MaxX &&
2198 109 : sLayerExtent.MinY < sLayerExtent.MaxY)
2199 : {
2200 214 : epsilon = std::min(sLayerExtent.MaxX - sLayerExtent.MinX,
2201 107 : sLayerExtent.MaxY - sLayerExtent.MinY) /
2202 : 10.0;
2203 : }
2204 :
2205 : /* -------------------------------------------------------------------- */
2206 : /* Construct inclusive filter. */
2207 : /* -------------------------------------------------------------------- */
2208 :
2209 422 : OGRLinearRing oRing;
2210 211 : oRing.setPoint(0, sEnvelope.MinX - 2 * epsilon,
2211 211 : sEnvelope.MinY - 2 * epsilon);
2212 211 : oRing.setPoint(1, sEnvelope.MinX - 2 * epsilon,
2213 211 : sEnvelope.MaxY + 1 * epsilon);
2214 211 : oRing.setPoint(2, sEnvelope.MaxX + 1 * epsilon,
2215 211 : sEnvelope.MaxY + 1 * epsilon);
2216 211 : oRing.setPoint(3, sEnvelope.MaxX + 1 * epsilon,
2217 211 : sEnvelope.MinY - 2 * epsilon);
2218 211 : oRing.setPoint(4, sEnvelope.MinX - 2 * epsilon,
2219 211 : sEnvelope.MinY - 2 * epsilon);
2220 :
2221 422 : OGRPolygon oInclusiveFilter;
2222 211 : oInclusiveFilter.addRing(&oRing);
2223 :
2224 211 : LOG_ACTION(poLayer->SetSpatialFilter(iGeomField, &oInclusiveFilter));
2225 :
2226 : /* -------------------------------------------------------------------- */
2227 : /* Verify that we can find the target feature. */
2228 : /* -------------------------------------------------------------------- */
2229 211 : bool bFound = false;
2230 211 : GIntBig nIterCount = 0;
2231 1804 : for (auto &&poFeature : poLayer)
2232 : {
2233 1593 : if (poFeature->Equal(poTargetFeature))
2234 : {
2235 211 : bFound = true;
2236 : }
2237 1593 : nIterCount++;
2238 : }
2239 :
2240 211 : if (!bFound)
2241 : {
2242 0 : bRet = FALSE;
2243 0 : printf(
2244 : "ERROR: Spatial filter (%d) eliminated a feature unexpectedly!\n",
2245 : iGeomField);
2246 : }
2247 211 : else if (bVerbose)
2248 : {
2249 211 : printf("INFO: Spatial filter inclusion seems to work.\n");
2250 : }
2251 :
2252 211 : GIntBig nInclusiveCount = LOG_ACTION(poLayer->GetFeatureCount());
2253 :
2254 : // Identity check doesn't always work depending on feature geometries
2255 211 : if (nIterCount > nInclusiveCount)
2256 : {
2257 0 : bRet = FALSE;
2258 0 : printf("ERROR: GetFeatureCount() with spatial filter smaller (%d) than "
2259 : "count while iterating over features (%d).\n",
2260 : static_cast<int>(nInclusiveCount), static_cast<int>(nIterCount));
2261 : }
2262 :
2263 211 : LOG_ACTION(poLayer->SetAttributeFilter("1=1"));
2264 211 : GIntBig nShouldBeSame = LOG_ACTION(poLayer->GetFeatureCount());
2265 211 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
2266 211 : if (nShouldBeSame != nInclusiveCount)
2267 : {
2268 0 : bRet = FALSE;
2269 0 : printf("ERROR: Attribute filter seems to be make spatial "
2270 : "filter fail with GetFeatureCount().\n");
2271 : }
2272 :
2273 211 : LOG_ACTION(poLayer->SetAttributeFilter("1=0"));
2274 211 : GIntBig nShouldBeZero = LOG_ACTION(poLayer->GetFeatureCount());
2275 211 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
2276 211 : if (nShouldBeZero != 0)
2277 : {
2278 0 : bRet = FALSE;
2279 0 : printf("ERROR: Attribute filter seems to be ignored in "
2280 : "GetFeatureCount() when spatial filter is set.\n");
2281 : }
2282 :
2283 : /* -------------------------------------------------------------------- */
2284 : /* Construct exclusive filter. */
2285 : /* -------------------------------------------------------------------- */
2286 211 : oRing.setPoint(0, sEnvelope.MinX - 2 * epsilon,
2287 211 : sEnvelope.MinY - 2 * epsilon);
2288 211 : oRing.setPoint(1, sEnvelope.MinX - 1 * epsilon,
2289 211 : sEnvelope.MinY - 2 * epsilon);
2290 211 : oRing.setPoint(2, sEnvelope.MinX - 1 * epsilon,
2291 211 : sEnvelope.MinY - 1 * epsilon);
2292 211 : oRing.setPoint(3, sEnvelope.MinX - 2 * epsilon,
2293 211 : sEnvelope.MinY - 1 * epsilon);
2294 211 : oRing.setPoint(4, sEnvelope.MinX - 2 * epsilon,
2295 211 : sEnvelope.MinY - 2 * epsilon);
2296 :
2297 422 : OGRPolygon oExclusiveFilter;
2298 211 : oExclusiveFilter.addRing(&oRing);
2299 :
2300 211 : LOG_ACTION(poLayer->SetSpatialFilter(iGeomField, &oExclusiveFilter));
2301 :
2302 : /* -------------------------------------------------------------------- */
2303 : /* Verify that we can NOT find the target feature. */
2304 : /* -------------------------------------------------------------------- */
2305 211 : OGRFeatureUniquePtr poUniquePtrFeature;
2306 283 : for (auto &&poFeatureIter : poLayer)
2307 : {
2308 72 : if (poFeatureIter->Equal(poTargetFeature))
2309 : {
2310 0 : poUniquePtrFeature.swap(poFeatureIter);
2311 0 : break;
2312 : }
2313 : }
2314 :
2315 211 : if (poUniquePtrFeature != nullptr)
2316 : {
2317 0 : bRet = FALSE;
2318 0 : printf("ERROR: Spatial filter (%d) failed to eliminate"
2319 : "a feature unexpectedly!\n",
2320 : iGeomField);
2321 : }
2322 211 : else if (LOG_ACTION(poLayer->GetFeatureCount()) >= nInclusiveCount)
2323 : {
2324 0 : bRet = FALSE;
2325 0 : printf("ERROR: GetFeatureCount() may not be taking spatial "
2326 : "filter (%d) into account.\n",
2327 : iGeomField);
2328 : }
2329 211 : else if (bVerbose)
2330 : {
2331 211 : printf("INFO: Spatial filter exclusion seems to work.\n");
2332 : }
2333 :
2334 : // Check that GetFeature() ignores the spatial filter
2335 422 : poUniquePtrFeature.reset(
2336 211 : LOG_ACTION(poLayer->GetFeature(poTargetFeature->GetFID())));
2337 422 : if (poUniquePtrFeature == nullptr ||
2338 211 : !poUniquePtrFeature->Equal(poTargetFeature))
2339 : {
2340 0 : bRet = FALSE;
2341 0 : printf("ERROR: Spatial filter has been taken into account "
2342 : "by GetFeature()\n");
2343 : }
2344 211 : else if (bVerbose)
2345 : {
2346 211 : printf("INFO: Spatial filter is ignored by GetFeature() "
2347 : "as expected.\n");
2348 : }
2349 :
2350 211 : if (bRet)
2351 : {
2352 211 : poUniquePtrFeature.reset();
2353 283 : for (auto &&poFeatureIter : poLayer)
2354 : {
2355 72 : if (poFeatureIter->Equal(poTargetFeature))
2356 : {
2357 0 : poUniquePtrFeature.swap(poFeatureIter);
2358 0 : break;
2359 : }
2360 : }
2361 211 : if (poUniquePtrFeature != nullptr)
2362 : {
2363 0 : bRet = FALSE;
2364 0 : printf("ERROR: Spatial filter has not been restored correctly "
2365 : "after GetFeature()\n");
2366 : }
2367 : }
2368 :
2369 211 : DestroyFeatureAndNullify(poTargetFeature);
2370 :
2371 : /* -------------------------------------------------------------------- */
2372 : /* Test infinity envelope */
2373 : /* -------------------------------------------------------------------- */
2374 :
2375 211 : constexpr double NEG_INF = -std::numeric_limits<double>::infinity();
2376 211 : constexpr double POS_INF = std::numeric_limits<double>::infinity();
2377 :
2378 211 : oRing.setPoint(0, NEG_INF, NEG_INF);
2379 211 : oRing.setPoint(1, NEG_INF, POS_INF);
2380 211 : oRing.setPoint(2, POS_INF, POS_INF);
2381 211 : oRing.setPoint(3, POS_INF, NEG_INF);
2382 211 : oRing.setPoint(4, NEG_INF, NEG_INF);
2383 :
2384 422 : OGRPolygon oInfinityFilter;
2385 211 : oInfinityFilter.addRing(&oRing);
2386 :
2387 211 : LOG_ACTION(poLayer->SetSpatialFilter(iGeomField, &oInfinityFilter));
2388 211 : int nCountInf = 0;
2389 2557 : for (auto &&poFeatureIter : poLayer)
2390 : {
2391 2346 : auto poGeomIter = poFeatureIter->GetGeomFieldRef(iGeomField);
2392 2346 : if (poGeomIter != nullptr)
2393 2346 : nCountInf++;
2394 : }
2395 :
2396 : /* -------------------------------------------------------------------- */
2397 : /* Test envelope with huge coords */
2398 : /* -------------------------------------------------------------------- */
2399 :
2400 211 : constexpr double HUGE_COORDS = 1.0e300;
2401 :
2402 211 : oRing.setPoint(0, -HUGE_COORDS, -HUGE_COORDS);
2403 211 : oRing.setPoint(1, -HUGE_COORDS, HUGE_COORDS);
2404 211 : oRing.setPoint(2, HUGE_COORDS, HUGE_COORDS);
2405 211 : oRing.setPoint(3, HUGE_COORDS, -HUGE_COORDS);
2406 211 : oRing.setPoint(4, -HUGE_COORDS, -HUGE_COORDS);
2407 :
2408 211 : OGRPolygon oHugeFilter;
2409 211 : oHugeFilter.addRing(&oRing);
2410 :
2411 211 : LOG_ACTION(poLayer->SetSpatialFilter(iGeomField, &oHugeFilter));
2412 211 : int nCountHuge = 0;
2413 2549 : for (auto &&poFeatureIter : poLayer)
2414 : {
2415 2338 : auto poGeomIter = poFeatureIter->GetGeomFieldRef(iGeomField);
2416 2338 : if (poGeomIter != nullptr)
2417 2338 : nCountHuge++;
2418 : }
2419 :
2420 : /* -------------------------------------------------------------------- */
2421 : /* Reset spatial filter */
2422 : /* -------------------------------------------------------------------- */
2423 211 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
2424 :
2425 211 : int nExpected = 0;
2426 2591 : for (auto &&poFeatureIter : poLayer)
2427 : {
2428 2380 : auto poGeomIter = poFeatureIter->GetGeomFieldRef(iGeomField);
2429 2380 : if (poGeomIter != nullptr && !poGeomIter->IsEmpty())
2430 2366 : nExpected++;
2431 : }
2432 211 : LOG_ACTION(poLayer->ResetReading());
2433 :
2434 211 : if (nCountInf != nExpected)
2435 : {
2436 : /*bRet = FALSE; */
2437 2 : printf("WARNING: Infinity spatial filter returned %d features "
2438 : "instead of %d\n",
2439 : nCountInf, nExpected);
2440 : }
2441 209 : else if (bVerbose)
2442 : {
2443 209 : printf("INFO: Infinity spatial filter works as expected.\n");
2444 : }
2445 :
2446 211 : if (nCountHuge != nExpected)
2447 : {
2448 : /* bRet = FALSE; */
2449 2 : printf("WARNING: Huge coords spatial filter returned %d features "
2450 : "instead of %d\n",
2451 : nCountHuge, nExpected);
2452 : }
2453 209 : else if (bVerbose)
2454 : {
2455 209 : printf("INFO: Huge coords spatial filter works as expected.\n");
2456 : }
2457 :
2458 211 : return bRet;
2459 : }
2460 :
2461 3 : static int TestFullSpatialFilter(OGRLayer *poLayer, int iGeomField)
2462 :
2463 : {
2464 3 : int bRet = TRUE;
2465 :
2466 3 : OGREnvelope sLayerExtent;
2467 3 : double epsilon = 10.0;
2468 3 : if (LOG_ACTION(poLayer->TestCapability(OLCFastGetExtent)) &&
2469 3 : LOG_ACTION(poLayer->GetExtent(iGeomField, &sLayerExtent)) ==
2470 3 : OGRERR_NONE &&
2471 8 : sLayerExtent.MinX < sLayerExtent.MaxX &&
2472 2 : sLayerExtent.MinY < sLayerExtent.MaxY)
2473 : {
2474 4 : epsilon = std::min(sLayerExtent.MaxX - sLayerExtent.MinX,
2475 2 : sLayerExtent.MaxY - sLayerExtent.MinY) /
2476 : 10.0;
2477 : }
2478 :
2479 3 : const GIntBig nTotalFeatureCount = LOG_ACTION(poLayer->GetFeatureCount());
2480 514 : for (GIntBig i = 0; i < nTotalFeatureCount; i++)
2481 : {
2482 : /* --------------------------------------------------------------------
2483 : */
2484 : /* Read the target feature. */
2485 : /* --------------------------------------------------------------------
2486 : */
2487 511 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
2488 511 : LOG_ACTION(poLayer->ResetReading());
2489 511 : LOG_ACTION(poLayer->SetNextByIndex(i));
2490 511 : OGRFeature *poTargetFeature = LOG_ACTION(poLayer->GetNextFeature());
2491 :
2492 511 : if (poTargetFeature == nullptr)
2493 : {
2494 0 : continue;
2495 : }
2496 :
2497 511 : OGRGeometry *poGeom = poTargetFeature->GetGeomFieldRef(iGeomField);
2498 511 : if (poGeom == nullptr || poGeom->IsEmpty())
2499 : {
2500 0 : DestroyFeatureAndNullify(poTargetFeature);
2501 0 : continue;
2502 : }
2503 :
2504 511 : OGREnvelope sEnvelope;
2505 511 : poGeom->getEnvelope(&sEnvelope);
2506 :
2507 : /* --------------------------------------------------------------------
2508 : */
2509 : /* Construct inclusive filter. */
2510 : /* --------------------------------------------------------------------
2511 : */
2512 :
2513 511 : OGRLinearRing oRing;
2514 511 : oRing.setPoint(0, sEnvelope.MinX - 2 * epsilon,
2515 511 : sEnvelope.MinY - 2 * epsilon);
2516 511 : oRing.setPoint(1, sEnvelope.MinX - 2 * epsilon,
2517 511 : sEnvelope.MaxY + 1 * epsilon);
2518 511 : oRing.setPoint(2, sEnvelope.MaxX + 1 * epsilon,
2519 511 : sEnvelope.MaxY + 1 * epsilon);
2520 511 : oRing.setPoint(3, sEnvelope.MaxX + 1 * epsilon,
2521 511 : sEnvelope.MinY - 2 * epsilon);
2522 511 : oRing.setPoint(4, sEnvelope.MinX - 2 * epsilon,
2523 511 : sEnvelope.MinY - 2 * epsilon);
2524 :
2525 511 : OGRPolygon oInclusiveFilter;
2526 511 : oInclusiveFilter.addRing(&oRing);
2527 :
2528 511 : LOG_ACTION(poLayer->SetSpatialFilter(iGeomField, &oInclusiveFilter));
2529 :
2530 : /* --------------------------------------------------------------------
2531 : */
2532 : /* Verify that we can find the target feature. */
2533 : /* --------------------------------------------------------------------
2534 : */
2535 511 : LOG_ACTION(poLayer->ResetReading());
2536 :
2537 511 : bool bFound = false;
2538 511 : OGRFeature *poFeature = nullptr;
2539 45101 : while ((poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
2540 : {
2541 45101 : if (poFeature->Equal(poTargetFeature))
2542 : {
2543 511 : bFound = true;
2544 511 : DestroyFeatureAndNullify(poFeature);
2545 511 : break;
2546 : }
2547 : else
2548 44590 : DestroyFeatureAndNullify(poFeature);
2549 : }
2550 :
2551 511 : if (!bFound)
2552 : {
2553 0 : bRet = FALSE;
2554 0 : printf("ERROR: Spatial filter (%d) eliminated feature " CPL_FRMT_GIB
2555 : " unexpectedly!\n",
2556 : iGeomField, poTargetFeature->GetFID());
2557 0 : DestroyFeatureAndNullify(poTargetFeature);
2558 0 : break;
2559 : }
2560 :
2561 511 : DestroyFeatureAndNullify(poTargetFeature);
2562 : }
2563 :
2564 : /* -------------------------------------------------------------------- */
2565 : /* Reset spatial filter */
2566 : /* -------------------------------------------------------------------- */
2567 3 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
2568 :
2569 3 : if (bRet && bVerbose)
2570 : {
2571 3 : printf("INFO: Full spatial filter succeeded.\n");
2572 : }
2573 :
2574 3 : return bRet;
2575 : }
2576 :
2577 302 : static int TestSpatialFilter(OGRLayer *poLayer)
2578 : {
2579 : /* -------------------------------------------------------------------- */
2580 : /* Read the target feature. */
2581 : /* -------------------------------------------------------------------- */
2582 302 : LOG_ACTION(poLayer->ResetReading());
2583 302 : OGRFeature *poTargetFeature = LOG_ACTION(poLayer->GetNextFeature());
2584 :
2585 302 : if (poTargetFeature == nullptr)
2586 : {
2587 13 : if (bVerbose)
2588 : {
2589 13 : printf("INFO: Skipping Spatial Filter test for %s.\n"
2590 : " No features in layer.\n",
2591 13 : poLayer->GetName());
2592 : }
2593 13 : return TRUE;
2594 : }
2595 289 : DestroyFeatureAndNullify(poTargetFeature);
2596 :
2597 : const int nGeomFieldCount =
2598 289 : LOG_ACTION(poLayer->GetLayerDefn()->GetGeomFieldCount());
2599 289 : if (nGeomFieldCount == 0)
2600 : {
2601 69 : if (bVerbose)
2602 : {
2603 69 : printf("INFO: Skipping Spatial Filter test for %s,\n"
2604 : " target feature has no geometry.\n",
2605 69 : poLayer->GetName());
2606 : }
2607 69 : return TRUE;
2608 : }
2609 :
2610 220 : int bRet = TRUE;
2611 453 : for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
2612 : {
2613 233 : bRet &= TestSpatialFilter(poLayer, iGeom);
2614 :
2615 233 : if (bFullSpatialFilter)
2616 3 : bRet &= TestFullSpatialFilter(poLayer, iGeom);
2617 : }
2618 :
2619 220 : CPLErrorReset();
2620 220 : CPLPushErrorHandler(CPLQuietErrorHandler);
2621 220 : OGRPolygon oPolygon;
2622 220 : LOG_ACTION(poLayer->SetSpatialFilter(-1, &oPolygon));
2623 220 : CPLPopErrorHandler();
2624 220 : if (CPLGetLastErrorType() == 0)
2625 0 : printf("WARNING: poLayer->SetSpatialFilter(-1) "
2626 : "should emit an error.\n");
2627 :
2628 220 : CPLErrorReset();
2629 220 : CPLPushErrorHandler(CPLQuietErrorHandler);
2630 220 : LOG_ACTION(poLayer->SetSpatialFilter(nGeomFieldCount, &oPolygon));
2631 220 : CPLPopErrorHandler();
2632 220 : if (CPLGetLastErrorType() == 0)
2633 0 : printf("WARNING: poLayer->SetSpatialFilter(nGeomFieldCount) "
2634 : "should emit an error.\n");
2635 :
2636 220 : return bRet;
2637 : }
2638 :
2639 : /************************************************************************/
2640 : /* GetQuotedIfNeededIdentifier() */
2641 : /************************************************************************/
2642 :
2643 1024 : static std::string GetQuotedIfNeededIdentifier(const char *pszFieldName)
2644 : {
2645 1024 : std::string osIdentifier;
2646 : const bool bMustQuoteAttrName =
2647 1020 : pszFieldName[0] == '\0' || strchr(pszFieldName, '_') ||
2648 2044 : strchr(pszFieldName, ' ') || swq_is_reserved_keyword(pszFieldName);
2649 1024 : if (bMustQuoteAttrName)
2650 : {
2651 292 : osIdentifier = "\"";
2652 292 : osIdentifier += pszFieldName;
2653 292 : osIdentifier += "\"";
2654 : }
2655 : else
2656 : {
2657 732 : osIdentifier = pszFieldName;
2658 : }
2659 1024 : return osIdentifier;
2660 : }
2661 :
2662 : /************************************************************************/
2663 : /* GetAttributeFilters() */
2664 : /************************************************************************/
2665 :
2666 604 : static bool GetAttributeFilters(OGRLayer *poLayer,
2667 : std::unique_ptr<OGRFeature> &poTargetFeature,
2668 : std::string &osInclusiveFilter,
2669 : std::string &osExclusiveFilter)
2670 : {
2671 :
2672 : /* -------------------------------------------------------------------- */
2673 : /* Read the target feature. */
2674 : /* -------------------------------------------------------------------- */
2675 604 : LOG_ACTION(poLayer->ResetReading());
2676 604 : poTargetFeature.reset(LOG_ACTION(poLayer->GetNextFeature()));
2677 :
2678 604 : if (poTargetFeature == nullptr)
2679 : {
2680 26 : if (bVerbose)
2681 : {
2682 26 : printf("INFO: Skipping Attribute Filter test for %s.\n"
2683 : " No features in layer.\n",
2684 26 : poLayer->GetName());
2685 : }
2686 26 : return false;
2687 : }
2688 :
2689 578 : int i = 0;
2690 578 : OGRFieldType eType = OFTString;
2691 668 : for (i = 0; i < poTargetFeature->GetFieldCount(); i++)
2692 : {
2693 602 : eType = poTargetFeature->GetFieldDefnRef(i)->GetType();
2694 1004 : if (poTargetFeature->IsFieldSetAndNotNull(i) &&
2695 402 : (eType == OFTString || eType == OFTInteger || eType == OFTReal))
2696 : {
2697 512 : break;
2698 : }
2699 : }
2700 578 : if (i == poTargetFeature->GetFieldCount())
2701 : {
2702 66 : if (bVerbose)
2703 : {
2704 66 : printf("INFO: Skipping Attribute Filter test for %s.\n"
2705 : " Could not find non NULL field.\n",
2706 66 : poLayer->GetName());
2707 : }
2708 66 : return false;
2709 : }
2710 :
2711 : const std::string osFieldName =
2712 1024 : poTargetFeature->GetFieldDefnRef(i)->GetNameRef();
2713 512 : CPLString osValue = poTargetFeature->GetFieldAsString(i);
2714 512 : if (eType == OFTReal)
2715 : {
2716 86 : int nWidth = poTargetFeature->GetFieldDefnRef(i)->GetWidth();
2717 86 : int nPrecision = poTargetFeature->GetFieldDefnRef(i)->GetPrecision();
2718 86 : if (nWidth > 0)
2719 : {
2720 : char szFormat[32];
2721 16 : snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth,
2722 : nPrecision);
2723 16 : osValue.Printf(szFormat, poTargetFeature->GetFieldAsDouble(i));
2724 : }
2725 : else
2726 70 : osValue.Printf("%.18g", poTargetFeature->GetFieldAsDouble(i));
2727 : }
2728 :
2729 : /* -------------------------------------------------------------------- */
2730 : /* Construct inclusive filter. */
2731 : /* -------------------------------------------------------------------- */
2732 512 : osInclusiveFilter = GetQuotedIfNeededIdentifier(osFieldName.c_str());
2733 512 : osInclusiveFilter += " = ";
2734 512 : if (eType == OFTString)
2735 170 : osInclusiveFilter += "'";
2736 512 : osInclusiveFilter += osValue;
2737 512 : if (eType == OFTString)
2738 170 : osInclusiveFilter += "'";
2739 : /* Make sure that the literal will be recognized as a float value */
2740 : /* to avoid int underflow/overflow */
2741 342 : else if (eType == OFTReal && strchr(osValue, '.') == nullptr)
2742 16 : osInclusiveFilter += ".";
2743 :
2744 : /* -------------------------------------------------------------------- */
2745 : /* Construct exclusive filter. */
2746 : /* -------------------------------------------------------------------- */
2747 512 : osExclusiveFilter = GetQuotedIfNeededIdentifier(osFieldName.c_str());
2748 512 : osExclusiveFilter += " <> ";
2749 512 : if (eType == OFTString)
2750 170 : osExclusiveFilter += "'";
2751 512 : osExclusiveFilter += osValue;
2752 512 : if (eType == OFTString)
2753 170 : osExclusiveFilter += "'";
2754 : /* Make sure that the literal will be recognized as a float value */
2755 : /* to avoid int underflow/overflow */
2756 342 : else if (eType == OFTReal && strchr(osValue, '.') == nullptr)
2757 16 : osExclusiveFilter += ".";
2758 :
2759 512 : return true;
2760 : }
2761 :
2762 : /************************************************************************/
2763 : /* TestAttributeFilter() */
2764 : /* */
2765 : /* This is intended to be a simple test of the attribute */
2766 : /* filtering. We read the first feature. Then construct a */
2767 : /* attribute filter which includes it, install and */
2768 : /* verify that we get the feature. Next install a attribute */
2769 : /* filter that doesn't include this feature, and test again. */
2770 : /************************************************************************/
2771 :
2772 302 : static int TestAttributeFilter(CPL_UNUSED GDALDataset *poDS, OGRLayer *poLayer)
2773 :
2774 : {
2775 302 : int bRet = TRUE;
2776 :
2777 302 : std::unique_ptr<OGRFeature> poTargetFeature;
2778 604 : std::string osInclusiveFilter;
2779 604 : std::string osExclusiveFilter;
2780 302 : if (!GetAttributeFilters(poLayer, poTargetFeature, osInclusiveFilter,
2781 : osExclusiveFilter))
2782 : {
2783 46 : return true;
2784 : }
2785 :
2786 : /* -------------------------------------------------------------------- */
2787 : /* Apply inclusive filter. */
2788 : /* -------------------------------------------------------------------- */
2789 256 : LOG_ACTION(poLayer->SetAttributeFilter(osInclusiveFilter.c_str()));
2790 :
2791 : /* -------------------------------------------------------------------- */
2792 : /* Verify that we can find the target feature. */
2793 : /* -------------------------------------------------------------------- */
2794 256 : LOG_ACTION(poLayer->ResetReading());
2795 :
2796 256 : bool bFoundFeature = false;
2797 256 : OGRFeature *poFeature = nullptr;
2798 256 : while ((poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
2799 : {
2800 256 : if (poFeature->Equal(poTargetFeature.get()))
2801 : {
2802 256 : bFoundFeature = true;
2803 256 : DestroyFeatureAndNullify(poFeature);
2804 256 : break;
2805 : }
2806 : else
2807 : {
2808 0 : DestroyFeatureAndNullify(poFeature);
2809 : }
2810 : }
2811 :
2812 256 : if (!bFoundFeature)
2813 : {
2814 0 : bRet = FALSE;
2815 0 : printf("ERROR: Attribute filter eliminated a feature unexpectedly!\n");
2816 : }
2817 256 : else if (bVerbose)
2818 : {
2819 256 : printf("INFO: Attribute filter inclusion seems to work.\n");
2820 : }
2821 :
2822 256 : const GIntBig nInclusiveCount = LOG_ACTION(poLayer->GetFeatureCount());
2823 :
2824 : /* -------------------------------------------------------------------- */
2825 : /* Apply exclusive filter. */
2826 : /* -------------------------------------------------------------------- */
2827 256 : LOG_ACTION(poLayer->SetAttributeFilter(osExclusiveFilter.c_str()));
2828 :
2829 : /* -------------------------------------------------------------------- */
2830 : /* Verify that we can find the target feature. */
2831 : /* -------------------------------------------------------------------- */
2832 256 : LOG_ACTION(poLayer->ResetReading());
2833 :
2834 256 : GIntBig nExclusiveCountWhileIterating = 0;
2835 2615 : while ((poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
2836 : {
2837 2359 : if (poFeature->Equal(poTargetFeature.get()))
2838 : {
2839 0 : DestroyFeatureAndNullify(poFeature);
2840 0 : break;
2841 : }
2842 : else
2843 : {
2844 2359 : DestroyFeatureAndNullify(poFeature);
2845 : }
2846 2359 : nExclusiveCountWhileIterating++;
2847 : }
2848 :
2849 256 : const GIntBig nExclusiveCount = LOG_ACTION(poLayer->GetFeatureCount());
2850 :
2851 : // Check that GetFeature() ignores the attribute filter
2852 : OGRFeature *poFeature2 =
2853 256 : LOG_ACTION(poLayer->GetFeature(poTargetFeature.get()->GetFID()));
2854 :
2855 256 : poLayer->ResetReading();
2856 256 : OGRFeature *poFeature3 = nullptr;
2857 2548 : while ((poFeature3 = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
2858 : {
2859 2300 : if (poFeature3->Equal(poTargetFeature.get()))
2860 : {
2861 8 : DestroyFeatureAndNullify(poFeature3);
2862 8 : break;
2863 : }
2864 : else
2865 2292 : DestroyFeatureAndNullify(poFeature3);
2866 : }
2867 :
2868 256 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
2869 :
2870 256 : const GIntBig nTotalCount = LOG_ACTION(poLayer->GetFeatureCount());
2871 :
2872 256 : if (poFeature != nullptr)
2873 : {
2874 0 : bRet = FALSE;
2875 0 : printf("ERROR: Attribute filter failed to eliminate "
2876 : "a feature unexpectedly!\n");
2877 : }
2878 256 : else if (nExclusiveCountWhileIterating != nExclusiveCount ||
2879 256 : nExclusiveCount >= nTotalCount || nInclusiveCount > nTotalCount ||
2880 50 : (nInclusiveCount == nTotalCount && nExclusiveCount != 0))
2881 : {
2882 0 : bRet = FALSE;
2883 0 : printf("ERROR: GetFeatureCount() may not be taking attribute "
2884 : "filter into account (nInclusiveCount = " CPL_FRMT_GIB
2885 : ", nExclusiveCount = " CPL_FRMT_GIB
2886 : ", nExclusiveCountWhileIterating = " CPL_FRMT_GIB
2887 : ", nTotalCount = " CPL_FRMT_GIB ").\n",
2888 : nInclusiveCount, nExclusiveCount, nExclusiveCountWhileIterating,
2889 : nTotalCount);
2890 : }
2891 256 : else if (bVerbose)
2892 : {
2893 256 : printf("INFO: Attribute filter exclusion seems to work.\n");
2894 : }
2895 :
2896 256 : if (poFeature2 == nullptr || !poFeature2->Equal(poTargetFeature.get()))
2897 : {
2898 0 : bRet = FALSE;
2899 0 : printf("ERROR: Attribute filter has been taken into account "
2900 : "by GetFeature()\n");
2901 : }
2902 256 : else if (bVerbose)
2903 : {
2904 256 : printf("INFO: Attribute filter is ignored by GetFeature() "
2905 : "as expected.\n");
2906 : }
2907 :
2908 256 : if (poFeature3 != nullptr)
2909 : {
2910 0 : bRet = FALSE;
2911 0 : printf("ERROR: Attribute filter has not been restored correctly "
2912 : "after GetFeature()\n");
2913 : }
2914 :
2915 256 : if (poFeature2 != nullptr)
2916 256 : DestroyFeatureAndNullify(poFeature2);
2917 :
2918 256 : return bRet;
2919 : }
2920 :
2921 : /************************************************************************/
2922 : /* TestOGRLayerUTF8() */
2923 : /************************************************************************/
2924 :
2925 302 : static int TestOGRLayerUTF8(OGRLayer *poLayer)
2926 : {
2927 302 : int bRet = TRUE;
2928 :
2929 302 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
2930 302 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
2931 302 : LOG_ACTION(poLayer->ResetReading());
2932 :
2933 : const int bIsAdvertizedAsUTF8 =
2934 302 : LOG_ACTION(poLayer->TestCapability(OLCStringsAsUTF8));
2935 302 : const int nFields = LOG_ACTION(poLayer->GetLayerDefn()->GetFieldCount());
2936 302 : bool bFoundString = false;
2937 302 : bool bFoundNonASCII = false;
2938 302 : bool bFoundUTF8 = false;
2939 302 : bool bCanAdvertiseUTF8 = true;
2940 :
2941 302 : OGRFeature *poFeature = nullptr;
2942 8146 : while (bRet &&
2943 4073 : (poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
2944 : {
2945 24375 : for (int i = 0; i < nFields; i++)
2946 : {
2947 20604 : if (!poFeature->IsFieldSet(i))
2948 1868 : continue;
2949 18736 : if (poFeature->GetFieldDefnRef(i)->GetType() == OFTString)
2950 : {
2951 5199 : const char *pszVal = poFeature->GetFieldAsString(i);
2952 5199 : if (pszVal[0] != 0)
2953 : {
2954 4636 : bFoundString = true;
2955 4636 : const GByte *pszIter =
2956 : reinterpret_cast<const GByte *>(pszVal);
2957 4636 : bool bIsASCII = true;
2958 65937 : while (*pszIter)
2959 : {
2960 61745 : if (*pszIter >= 128)
2961 : {
2962 444 : bFoundNonASCII = true;
2963 444 : bIsASCII = false;
2964 444 : break;
2965 : }
2966 61301 : pszIter++;
2967 : }
2968 4636 : int bIsUTF8 = CPLIsUTF8(pszVal, -1);
2969 4636 : if (bIsUTF8 && !bIsASCII)
2970 444 : bFoundUTF8 = true;
2971 4636 : if (bIsAdvertizedAsUTF8)
2972 : {
2973 4235 : if (!bIsUTF8)
2974 : {
2975 0 : printf("ERROR: Found non-UTF8 content at field %d "
2976 : "of feature " CPL_FRMT_GIB
2977 : ", but layer is advertized as UTF-8.\n",
2978 : i, poFeature->GetFID());
2979 0 : bRet = FALSE;
2980 0 : break;
2981 : }
2982 : }
2983 : else
2984 : {
2985 401 : if (!bIsUTF8)
2986 0 : bCanAdvertiseUTF8 = false;
2987 : }
2988 : }
2989 : }
2990 : }
2991 3771 : DestroyFeatureAndNullify(poFeature);
2992 : }
2993 :
2994 302 : if (!bFoundString)
2995 : {
2996 : }
2997 239 : else if (bCanAdvertiseUTF8 && bVerbose)
2998 : {
2999 239 : if (bIsAdvertizedAsUTF8)
3000 : {
3001 183 : if (bFoundUTF8)
3002 : {
3003 86 : printf("INFO: Layer has UTF-8 content and is consistently "
3004 : "declared as having UTF-8 content.\n");
3005 : }
3006 97 : else if (!bFoundNonASCII)
3007 : {
3008 97 : printf("INFO: Layer has ASCII only content and is "
3009 : "consistently declared as having UTF-8 content.\n");
3010 : }
3011 : }
3012 : else
3013 : {
3014 56 : if (bFoundUTF8)
3015 : {
3016 0 : printf("INFO: Layer could perhaps be advertized as UTF-8 "
3017 : "compatible (and it has non-ASCII UTF-8 content).\n");
3018 : }
3019 56 : else if (!bFoundNonASCII)
3020 : {
3021 56 : printf("INFO: Layer could perhaps be advertized as UTF-8 "
3022 : "compatible (it has only ASCII content).\n");
3023 : }
3024 : }
3025 : }
3026 0 : else if (bVerbose)
3027 : {
3028 0 : printf("INFO: Layer has non UTF-8 content (and is consistently "
3029 : "declared as not being UTF-8 compatible).\n");
3030 : }
3031 :
3032 302 : return bRet;
3033 : }
3034 :
3035 : /************************************************************************/
3036 : /* TestGetExtent() */
3037 : /************************************************************************/
3038 :
3039 241 : static int TestGetExtent(OGRLayer *poLayer, int iGeomField)
3040 : {
3041 241 : int bRet = TRUE;
3042 :
3043 241 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
3044 241 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
3045 241 : LOG_ACTION(poLayer->ResetReading());
3046 :
3047 241 : OGREnvelope sExtent;
3048 241 : OGREnvelope sExtentSlow;
3049 :
3050 241 : OGRErr eErr = LOG_ACTION(poLayer->GetExtent(iGeomField, &sExtent, TRUE));
3051 241 : OGRErr eErr2 = LOG_ACTION(
3052 : poLayer->OGRLayer::GetExtent(iGeomField, &sExtentSlow, TRUE));
3053 :
3054 241 : if (eErr != eErr2)
3055 : {
3056 0 : if (eErr == OGRERR_NONE && eErr2 != OGRERR_NONE)
3057 : {
3058 : // With the LIBKML driver and test_ogrsf:
3059 : // ../autotest/ogr/data/samples.kml "Styles and Markup"
3060 0 : if (bVerbose)
3061 : {
3062 0 : printf("INFO: GetExtent() succeeded but OGRLayer::GetExtent() "
3063 : "failed.\n");
3064 : }
3065 : }
3066 : else
3067 : {
3068 0 : bRet = FALSE;
3069 0 : if (bVerbose)
3070 : {
3071 0 : printf("ERROR: GetExtent() failed but OGRLayer::GetExtent() "
3072 : "succeeded.\n");
3073 : }
3074 : }
3075 : }
3076 241 : else if (eErr == OGRERR_NONE && bVerbose)
3077 : {
3078 201 : if (fabs(sExtentSlow.MinX - sExtent.MinX) < 1e-10 &&
3079 200 : fabs(sExtentSlow.MinY - sExtent.MinY) < 1e-10 &&
3080 200 : fabs(sExtentSlow.MaxX - sExtent.MaxX) < 1e-10 &&
3081 200 : fabs(sExtentSlow.MaxY - sExtent.MaxY) < 1e-10)
3082 : {
3083 200 : printf("INFO: GetExtent() test passed.\n");
3084 : }
3085 : else
3086 : {
3087 1 : if (sExtentSlow.Contains(sExtent))
3088 : {
3089 0 : printf("INFO: sExtentSlow.Contains(sExtent)\n");
3090 : }
3091 1 : else if (sExtent.Contains(sExtentSlow))
3092 : {
3093 0 : printf("INFO: sExtent.Contains(sExtentSlow)\n");
3094 : }
3095 : else
3096 : {
3097 1 : printf("INFO: unknown relationship between sExtent and "
3098 : "sExtentSlow.\n");
3099 : }
3100 1 : printf("INFO: sExtentSlow.MinX = %.15f\n", sExtentSlow.MinX);
3101 1 : printf("INFO: sExtentSlow.MinY = %.15f\n", sExtentSlow.MinY);
3102 1 : printf("INFO: sExtentSlow.MaxX = %.15f\n", sExtentSlow.MaxX);
3103 1 : printf("INFO: sExtentSlow.MaxY = %.15f\n", sExtentSlow.MaxY);
3104 1 : printf("INFO: sExtent.MinX = %.15f\n", sExtent.MinX);
3105 1 : printf("INFO: sExtent.MinY = %.15f\n", sExtent.MinY);
3106 1 : printf("INFO: sExtent.MaxX = %.15f\n", sExtent.MaxX);
3107 1 : printf("INFO: sExtent.MaxY = %.15f\n", sExtent.MaxY);
3108 : }
3109 : }
3110 :
3111 241 : return bRet;
3112 : }
3113 :
3114 302 : static int TestGetExtent(OGRLayer *poLayer)
3115 : {
3116 302 : int bRet = TRUE;
3117 : const int nGeomFieldCount =
3118 302 : LOG_ACTION(poLayer->GetLayerDefn()->GetGeomFieldCount());
3119 543 : for (int iGeom = 0; iGeom < nGeomFieldCount; iGeom++)
3120 241 : bRet &= TestGetExtent(poLayer, iGeom);
3121 :
3122 302 : OGREnvelope sExtent;
3123 302 : CPLPushErrorHandler(CPLQuietErrorHandler);
3124 302 : OGRErr eErr = LOG_ACTION(poLayer->GetExtent(-1, &sExtent, TRUE));
3125 302 : CPLPopErrorHandler();
3126 302 : if (eErr != OGRERR_FAILURE)
3127 : {
3128 0 : printf("ERROR: poLayer->GetExtent(-1) should fail.\n");
3129 0 : bRet = FALSE;
3130 : }
3131 :
3132 302 : CPLPushErrorHandler(CPLQuietErrorHandler);
3133 302 : eErr = LOG_ACTION(poLayer->GetExtent(nGeomFieldCount, &sExtent, TRUE));
3134 302 : CPLPopErrorHandler();
3135 302 : if (eErr != OGRERR_FAILURE)
3136 : {
3137 0 : printf("ERROR: poLayer->GetExtent(nGeomFieldCount) should fail.\n");
3138 0 : bRet = FALSE;
3139 : }
3140 :
3141 302 : return bRet;
3142 : }
3143 :
3144 : /*************************************************************************/
3145 : /* TestOGRLayerDeleteAndCreateFeature() */
3146 : /* */
3147 : /* Test delete feature by trying to delete the last feature and */
3148 : /* recreate it. */
3149 : /*************************************************************************/
3150 :
3151 31 : static int TestOGRLayerDeleteAndCreateFeature(OGRLayer *poLayer)
3152 :
3153 : {
3154 31 : int bRet = TRUE;
3155 :
3156 31 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
3157 :
3158 31 : if (!LOG_ACTION(poLayer->TestCapability(OLCRandomRead)))
3159 : {
3160 1 : if (bVerbose)
3161 1 : printf("INFO: Skipping delete feature test since this layer "
3162 : "doesn't support random read.\n");
3163 1 : return bRet;
3164 : }
3165 :
3166 30 : if (LOG_ACTION(poLayer->GetFeatureCount()) == 0)
3167 : {
3168 0 : if (bVerbose)
3169 0 : printf("INFO: No feature available on layer '%s',"
3170 : "skipping delete/create feature test.\n",
3171 0 : poLayer->GetName());
3172 :
3173 0 : return bRet;
3174 : }
3175 : /* -------------------------------------------------------------------- */
3176 : /* Fetch the last feature */
3177 : /* -------------------------------------------------------------------- */
3178 30 : OGRFeature *poFeatureTest = nullptr;
3179 30 : GIntBig nFID = 0;
3180 :
3181 30 : LOG_ACTION(poLayer->ResetReading());
3182 :
3183 30 : LOG_ACTION(poLayer->SetNextByIndex(poLayer->GetFeatureCount() - 1));
3184 30 : OGRFeature *poFeature = LOG_ACTION(poLayer->GetNextFeature());
3185 30 : if (poFeature == nullptr)
3186 : {
3187 0 : bRet = FALSE;
3188 0 : printf("ERROR: Could not get last feature of layer.\n");
3189 0 : goto end;
3190 : }
3191 :
3192 : /* -------------------------------------------------------------------- */
3193 : /* Get the feature ID of the last feature */
3194 : /* -------------------------------------------------------------------- */
3195 30 : nFID = poFeature->GetFID();
3196 :
3197 : /* -------------------------------------------------------------------- */
3198 : /* Delete the feature. */
3199 : /* -------------------------------------------------------------------- */
3200 :
3201 30 : if (LOG_ACTION(poLayer->DeleteFeature(nFID)) != OGRERR_NONE)
3202 : {
3203 0 : bRet = FALSE;
3204 0 : printf("ERROR: Attempt to DeleteFeature() failed.\n");
3205 0 : goto end;
3206 : }
3207 :
3208 : /* -------------------------------------------------------------------- */
3209 : /* Now re-read the feature to verify the delete effect worked. */
3210 : /* -------------------------------------------------------------------- */
3211 : // Silent legitimate error message.
3212 30 : CPLPushErrorHandler(CPLQuietErrorHandler);
3213 30 : poFeatureTest = LOG_ACTION(poLayer->GetFeature(nFID));
3214 30 : CPLPopErrorHandler();
3215 30 : if (poFeatureTest != nullptr)
3216 : {
3217 6 : bRet = FALSE;
3218 6 : printf("ERROR: The feature was not deleted.\n");
3219 : }
3220 24 : else if (bVerbose)
3221 : {
3222 24 : printf("INFO: Delete Feature test passed.\n");
3223 : }
3224 30 : DestroyFeatureAndNullify(poFeatureTest);
3225 :
3226 : /* -------------------------------------------------------------------- */
3227 : /* Re-insert the features to restore to original state */
3228 : /* -------------------------------------------------------------------- */
3229 30 : if (LOG_ACTION(poLayer->CreateFeature(poFeature)) != OGRERR_NONE)
3230 : {
3231 6 : bRet = FALSE;
3232 6 : printf("ERROR: Attempt to restore feature failed.\n");
3233 : }
3234 :
3235 30 : if (poFeature->GetFID() != nFID)
3236 : {
3237 : /* Case of shapefile driver for example that will not try to */
3238 : /* reuse the existing FID, but will assign a new one */
3239 2 : if (bVerbose)
3240 : {
3241 2 : printf("INFO: Feature was created, "
3242 : "but with not its original FID.\n");
3243 : }
3244 2 : nFID = poFeature->GetFID();
3245 : }
3246 :
3247 : /* -------------------------------------------------------------------- */
3248 : /* Now re-read the feature to verify the create effect worked. */
3249 : /* -------------------------------------------------------------------- */
3250 30 : poFeatureTest = LOG_ACTION(poLayer->GetFeature(nFID));
3251 30 : if (poFeatureTest == nullptr)
3252 : {
3253 0 : bRet = FALSE;
3254 0 : printf("ERROR: The feature was not created.\n");
3255 : }
3256 30 : else if (bVerbose)
3257 : {
3258 30 : printf("INFO: Create Feature test passed.\n");
3259 : }
3260 30 : DestroyFeatureAndNullify(poFeatureTest);
3261 :
3262 30 : end:
3263 : /* -------------------------------------------------------------------- */
3264 : /* Cleanup. */
3265 : /* -------------------------------------------------------------------- */
3266 :
3267 30 : DestroyFeatureAndNullify(poFeature);
3268 :
3269 30 : return bRet;
3270 : }
3271 :
3272 : /*************************************************************************/
3273 : /* TestTransactions() */
3274 : /*************************************************************************/
3275 :
3276 46 : static int TestTransactions(OGRLayer *poLayer)
3277 :
3278 : {
3279 46 : GIntBig nInitialFeatureCount = LOG_ACTION(poLayer->GetFeatureCount());
3280 :
3281 46 : OGRErr eErr = LOG_ACTION(poLayer->StartTransaction());
3282 46 : if (eErr == OGRERR_NONE)
3283 : {
3284 46 : if (LOG_ACTION(poLayer->TestCapability(OLCTransactions)) == FALSE)
3285 : {
3286 34 : eErr = LOG_ACTION(poLayer->RollbackTransaction());
3287 68 : if (eErr == OGRERR_UNSUPPORTED_OPERATION &&
3288 34 : LOG_ACTION(poLayer->TestCapability(OLCTransactions)) == FALSE)
3289 : {
3290 : // The default implementation has a dummy
3291 : // StartTransaction(), but RollbackTransaction()
3292 : // returns OGRERR_UNSUPPORTED_OPERATION
3293 34 : if (bVerbose)
3294 : {
3295 34 : printf("INFO: Transactions test skipped due to lack of "
3296 : "transaction support.\n");
3297 : }
3298 34 : return TRUE;
3299 : }
3300 : else
3301 : {
3302 0 : printf("WARN: StartTransaction() is supported, but "
3303 : "TestCapability(OLCTransactions) returns FALSE.\n");
3304 : }
3305 : }
3306 : }
3307 0 : else if (eErr == OGRERR_FAILURE)
3308 : {
3309 0 : if (LOG_ACTION(poLayer->TestCapability(OLCTransactions)) == TRUE)
3310 : {
3311 0 : printf("ERROR: StartTransaction() failed, but "
3312 : "TestCapability(OLCTransactions) returns TRUE.\n");
3313 0 : return FALSE;
3314 : }
3315 : else
3316 : {
3317 0 : return TRUE;
3318 : }
3319 : }
3320 :
3321 12 : eErr = LOG_ACTION(poLayer->RollbackTransaction());
3322 12 : if (eErr != OGRERR_NONE)
3323 : {
3324 0 : printf("ERROR: RollbackTransaction() failed after successful "
3325 : "StartTransaction().\n");
3326 0 : return FALSE;
3327 : }
3328 :
3329 : /* ---------------- */
3330 :
3331 12 : eErr = LOG_ACTION(poLayer->StartTransaction());
3332 12 : if (eErr != OGRERR_NONE)
3333 : {
3334 0 : printf("ERROR: StartTransaction() failed.\n");
3335 0 : return FALSE;
3336 : }
3337 :
3338 12 : eErr = LOG_ACTION(poLayer->CommitTransaction());
3339 12 : if (eErr != OGRERR_NONE)
3340 : {
3341 0 : printf("ERROR: CommitTransaction() failed after successful "
3342 : "StartTransaction().\n");
3343 0 : return FALSE;
3344 : }
3345 :
3346 : /* ---------------- */
3347 :
3348 12 : eErr = LOG_ACTION(poLayer->StartTransaction());
3349 12 : if (eErr != OGRERR_NONE)
3350 : {
3351 0 : printf("ERROR: StartTransaction() failed.\n");
3352 0 : return FALSE;
3353 : }
3354 :
3355 12 : OGRFeature *poFeature = new OGRFeature(poLayer->GetLayerDefn());
3356 12 : if (poLayer->GetLayerDefn()->GetFieldCount() > 0)
3357 11 : poFeature->SetField(0, "0");
3358 12 : eErr = LOG_ACTION(poLayer->CreateFeature(poFeature));
3359 12 : delete poFeature;
3360 12 : poFeature = nullptr;
3361 :
3362 12 : if (eErr == OGRERR_FAILURE)
3363 : {
3364 0 : if (bVerbose)
3365 : {
3366 0 : printf("INFO: CreateFeature() failed. Exiting this test now.\n");
3367 : }
3368 0 : LOG_ACTION(poLayer->RollbackTransaction());
3369 0 : return TRUE;
3370 : }
3371 :
3372 12 : eErr = LOG_ACTION(poLayer->RollbackTransaction());
3373 12 : if (eErr != OGRERR_NONE)
3374 : {
3375 0 : printf("ERROR: RollbackTransaction() failed after successful "
3376 : "StartTransaction().\n");
3377 0 : return FALSE;
3378 : }
3379 :
3380 12 : if (LOG_ACTION(poLayer->GetFeatureCount()) != nInitialFeatureCount)
3381 : {
3382 0 : printf("ERROR: GetFeatureCount() should have returned its initial "
3383 : "value after RollbackTransaction().\n");
3384 0 : return FALSE;
3385 : }
3386 :
3387 : /* ---------------- */
3388 :
3389 12 : if (LOG_ACTION(poLayer->TestCapability(OLCDeleteFeature)))
3390 : {
3391 12 : eErr = LOG_ACTION(poLayer->StartTransaction());
3392 12 : if (eErr != OGRERR_NONE)
3393 : {
3394 0 : printf("ERROR: StartTransaction() failed.\n");
3395 0 : return FALSE;
3396 : }
3397 :
3398 12 : poFeature = new OGRFeature(poLayer->GetLayerDefn());
3399 12 : if (poLayer->GetLayerDefn()->GetFieldCount() > 0)
3400 11 : poFeature->SetField(0, "0");
3401 12 : eErr = poLayer->CreateFeature(poFeature);
3402 12 : GIntBig nFID = poFeature->GetFID();
3403 12 : delete poFeature;
3404 12 : poFeature = nullptr;
3405 :
3406 12 : if (eErr == OGRERR_FAILURE)
3407 : {
3408 0 : printf("ERROR: CreateFeature() failed. Exiting this test now.\n");
3409 0 : LOG_ACTION(poLayer->RollbackTransaction());
3410 0 : return FALSE;
3411 : }
3412 :
3413 12 : if (nFID < 0)
3414 : {
3415 0 : printf("WARNING: CreateFeature() returned featured without FID.\n");
3416 0 : LOG_ACTION(poLayer->RollbackTransaction());
3417 0 : return FALSE;
3418 : }
3419 :
3420 12 : eErr = LOG_ACTION(poLayer->CommitTransaction());
3421 12 : if (eErr != OGRERR_NONE)
3422 : {
3423 0 : printf("ERROR: CommitTransaction() failed after successful "
3424 : "StartTransaction().\n");
3425 0 : return FALSE;
3426 : }
3427 :
3428 12 : if (LOG_ACTION(poLayer->GetFeatureCount()) != nInitialFeatureCount + 1)
3429 : {
3430 0 : printf("ERROR: GetFeatureCount() should have returned its initial "
3431 : "value + 1 after CommitTransaction().\n");
3432 0 : return FALSE;
3433 : }
3434 :
3435 12 : eErr = LOG_ACTION(poLayer->DeleteFeature(nFID));
3436 12 : if (eErr != OGRERR_NONE)
3437 : {
3438 0 : printf("ERROR: DeleteFeature() failed.\n");
3439 0 : return FALSE;
3440 : }
3441 :
3442 12 : if (LOG_ACTION(poLayer->GetFeatureCount()) != nInitialFeatureCount)
3443 : {
3444 0 : printf("ERROR: GetFeatureCount() should have returned its initial "
3445 : "value after DeleteFeature().\n");
3446 0 : return FALSE;
3447 : }
3448 : }
3449 :
3450 : /* ---------------- */
3451 :
3452 12 : if (bVerbose)
3453 : {
3454 12 : printf("INFO: Transactions test passed.\n");
3455 : }
3456 :
3457 12 : return TRUE;
3458 : }
3459 :
3460 : /************************************************************************/
3461 : /* TestOGRLayerIgnoreFields() */
3462 : /************************************************************************/
3463 :
3464 132 : static int TestOGRLayerIgnoreFields(OGRLayer *poLayer)
3465 : {
3466 132 : int iFieldNonEmpty = -1;
3467 132 : int iFieldNonEmpty2 = -1;
3468 132 : bool bGeomNonEmpty = false;
3469 :
3470 132 : LOG_ACTION(poLayer->ResetReading());
3471 132 : OGRFeature *poFeature = nullptr;
3472 1911 : while ((poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
3473 : {
3474 1779 : if (iFieldNonEmpty < 0)
3475 : {
3476 157 : for (int i = 0; i < poFeature->GetFieldCount(); i++)
3477 : {
3478 108 : if (poFeature->IsFieldSetAndNotNull(i))
3479 : {
3480 108 : iFieldNonEmpty = i;
3481 108 : break;
3482 : }
3483 : }
3484 : }
3485 1622 : else if (iFieldNonEmpty2 < 0)
3486 : {
3487 2324 : for (int i = 0; i < poFeature->GetFieldCount(); i++)
3488 : {
3489 1275 : if (i != iFieldNonEmpty && poFeature->IsFieldSetAndNotNull(i))
3490 : {
3491 98 : iFieldNonEmpty2 = i;
3492 98 : break;
3493 : }
3494 : }
3495 : }
3496 :
3497 1779 : if (!bGeomNonEmpty && poFeature->GetGeometryRef() != nullptr)
3498 102 : bGeomNonEmpty = true;
3499 :
3500 1779 : delete poFeature;
3501 : }
3502 :
3503 132 : if (iFieldNonEmpty < 0 && !bGeomNonEmpty)
3504 : {
3505 7 : if (bVerbose)
3506 : {
3507 7 : printf("INFO: IgnoreFields test skipped.\n");
3508 : }
3509 7 : return TRUE;
3510 : }
3511 :
3512 125 : char **papszIgnoredFields = nullptr;
3513 125 : if (iFieldNonEmpty >= 0)
3514 : papszIgnoredFields =
3515 216 : CSLAddString(papszIgnoredFields, poLayer->GetLayerDefn()
3516 108 : ->GetFieldDefn(iFieldNonEmpty)
3517 : ->GetNameRef());
3518 :
3519 125 : if (bGeomNonEmpty)
3520 102 : papszIgnoredFields = CSLAddString(papszIgnoredFields, "OGR_GEOMETRY");
3521 :
3522 125 : OGRErr eErr = LOG_ACTION(poLayer->SetIgnoredFields(
3523 : const_cast<const char **>(papszIgnoredFields)));
3524 125 : CSLDestroy(papszIgnoredFields);
3525 :
3526 125 : if (eErr == OGRERR_FAILURE)
3527 : {
3528 0 : printf("ERROR: SetIgnoredFields() failed.\n");
3529 0 : poLayer->SetIgnoredFields(nullptr);
3530 0 : return FALSE;
3531 : }
3532 :
3533 125 : bool bFoundNonEmpty2 = false;
3534 :
3535 125 : LOG_ACTION(poLayer->ResetReading());
3536 1888 : while ((poFeature = LOG_ACTION(poLayer->GetNextFeature())) != nullptr)
3537 : {
3538 3493 : if (iFieldNonEmpty >= 0 &&
3539 1730 : poFeature->IsFieldSetAndNotNull(iFieldNonEmpty))
3540 : {
3541 0 : delete poFeature;
3542 0 : printf("ERROR: After SetIgnoredFields(), "
3543 : "found a non empty field that should have been ignored.\n");
3544 0 : poLayer->SetIgnoredFields(nullptr);
3545 0 : return FALSE;
3546 : }
3547 :
3548 2437 : if (iFieldNonEmpty2 >= 0 &&
3549 674 : poFeature->IsFieldSetAndNotNull(iFieldNonEmpty2))
3550 658 : bFoundNonEmpty2 = true;
3551 :
3552 1763 : if (bGeomNonEmpty && poFeature->GetGeometryRef() != nullptr)
3553 : {
3554 0 : delete poFeature;
3555 0 : printf(
3556 : "ERROR: After SetIgnoredFields(), "
3557 : "found a non empty geometry that should have been ignored.\n");
3558 0 : poLayer->SetIgnoredFields(nullptr);
3559 0 : return FALSE;
3560 : }
3561 :
3562 1763 : delete poFeature;
3563 : }
3564 :
3565 125 : if (iFieldNonEmpty2 >= 0 && !bFoundNonEmpty2)
3566 : {
3567 0 : printf("ERROR: SetIgnoredFields() discarded fields that it "
3568 : "should not have discarded.\n");
3569 0 : poLayer->SetIgnoredFields(nullptr);
3570 0 : return FALSE;
3571 : }
3572 :
3573 125 : LOG_ACTION(poLayer->SetIgnoredFields(nullptr));
3574 :
3575 125 : if (bVerbose)
3576 : {
3577 125 : printf("INFO: IgnoreFields test passed.\n");
3578 : }
3579 :
3580 125 : return TRUE;
3581 : }
3582 :
3583 : /************************************************************************/
3584 : /* TestLayerSQL() */
3585 : /************************************************************************/
3586 :
3587 292 : static int TestLayerSQL(GDALDataset *poDS, OGRLayer *poLayer)
3588 :
3589 : {
3590 292 : int bRet = TRUE;
3591 292 : bool bGotFeature = false;
3592 :
3593 : /* Test consistency between result layer and traditional layer */
3594 292 : LOG_ACTION(poLayer->ResetReading());
3595 292 : OGRFeature *poLayerFeat = LOG_ACTION(poLayer->GetNextFeature());
3596 :
3597 : /* Reset to avoid potentially a statement to be active which cause */
3598 : /* issue in the transaction test of the second layer, when testing */
3599 : /* multi-tables sqlite and gpkg databases */
3600 292 : LOG_ACTION(poLayer->ResetReading());
3601 :
3602 584 : CPLString osSQL;
3603 : osSQL.Printf("SELECT * FROM %s",
3604 292 : GetLayerNameForSQL(poDS, poLayer->GetName()));
3605 : OGRLayer *poSQLLyr =
3606 292 : LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), nullptr, nullptr));
3607 292 : OGRFeature *poSQLFeat = nullptr;
3608 292 : if (poSQLLyr == nullptr)
3609 : {
3610 0 : printf("ERROR: ExecuteSQL(%s) failed.\n", osSQL.c_str());
3611 0 : bRet = FALSE;
3612 0 : return bRet;
3613 : }
3614 : else
3615 : {
3616 292 : poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
3617 292 : if (poSQLFeat != nullptr)
3618 273 : bGotFeature = TRUE;
3619 292 : if (poLayerFeat == nullptr && poSQLFeat != nullptr)
3620 : {
3621 0 : printf("ERROR: poLayerFeat == NULL && poSQLFeat != NULL.\n");
3622 0 : bRet = FALSE;
3623 : }
3624 292 : else if (poLayerFeat != nullptr && poSQLFeat == nullptr)
3625 : {
3626 0 : printf("ERROR: poLayerFeat != NULL && poSQLFeat == NULL.\n");
3627 0 : bRet = FALSE;
3628 : }
3629 292 : else if (poLayerFeat != nullptr && poSQLFeat != nullptr)
3630 : {
3631 273 : if (poLayer->GetLayerDefn()->GetGeomFieldCount() !=
3632 273 : poSQLLyr->GetLayerDefn()->GetGeomFieldCount())
3633 : {
3634 0 : printf("ERROR: poLayer->GetLayerDefn()->GetGeomFieldCount() != "
3635 : "poSQLLyr->GetLayerDefn()->GetGeomFieldCount().\n");
3636 0 : bRet = FALSE;
3637 : }
3638 : else
3639 : {
3640 : int nGeomFieldCount =
3641 273 : poLayer->GetLayerDefn()->GetGeomFieldCount();
3642 492 : for (int i = 0; i < nGeomFieldCount; i++)
3643 : {
3644 : int iOtherI;
3645 219 : if (nGeomFieldCount != 1)
3646 : {
3647 : OGRGeomFieldDefn *poGFldDefn =
3648 22 : poLayer->GetLayerDefn()->GetGeomFieldDefn(i);
3649 44 : iOtherI = poSQLLyr->GetLayerDefn()->GetGeomFieldIndex(
3650 22 : poGFldDefn->GetNameRef());
3651 22 : if (iOtherI == -1)
3652 : {
3653 0 : printf("ERROR: Cannot find geom field in SQL "
3654 : "matching %s.\n",
3655 : poGFldDefn->GetNameRef());
3656 0 : break;
3657 : }
3658 : }
3659 : else
3660 197 : iOtherI = 0;
3661 : OGRGeometry *poLayerFeatGeom =
3662 219 : poLayerFeat->GetGeomFieldRef(i);
3663 : OGRGeometry *poSQLFeatGeom =
3664 219 : poSQLFeat->GetGeomFieldRef(iOtherI);
3665 219 : if (poLayerFeatGeom == nullptr && poSQLFeatGeom != nullptr)
3666 : {
3667 0 : printf("ERROR: poLayerFeatGeom[%d] == NULL && "
3668 : "poSQLFeatGeom[%d] != NULL.\n",
3669 : i, iOtherI);
3670 0 : bRet = FALSE;
3671 : }
3672 219 : else if (poLayerFeatGeom != nullptr &&
3673 : poSQLFeatGeom == nullptr)
3674 : {
3675 0 : printf("ERROR: poLayerFeatGeom[%d] != NULL && "
3676 : "poSQLFeatGeom[%d] == NULL.\n",
3677 : i, iOtherI);
3678 0 : bRet = FALSE;
3679 : }
3680 219 : else if (poLayerFeatGeom != nullptr &&
3681 : poSQLFeatGeom != nullptr)
3682 : {
3683 : const OGRSpatialReference *poLayerFeatSRS =
3684 197 : poLayerFeatGeom->getSpatialReference();
3685 : const OGRSpatialReference *poSQLFeatSRS =
3686 197 : poSQLFeatGeom->getSpatialReference();
3687 197 : if (poLayerFeatSRS == nullptr &&
3688 : poSQLFeatSRS != nullptr)
3689 : {
3690 0 : printf("ERROR: poLayerFeatSRS == NULL && "
3691 : "poSQLFeatSRS != NULL.\n");
3692 0 : bRet = FALSE;
3693 : }
3694 197 : else if (poLayerFeatSRS != nullptr &&
3695 : poSQLFeatSRS == nullptr)
3696 : {
3697 0 : printf("ERROR: poLayerFeatSRS != NULL && "
3698 : "poSQLFeatSRS == NULL.\n");
3699 0 : bRet = FALSE;
3700 : }
3701 197 : else if (poLayerFeatSRS != nullptr &&
3702 : poSQLFeatSRS != nullptr)
3703 : {
3704 171 : if (!(poLayerFeatSRS->IsSame(poSQLFeatSRS)))
3705 : {
3706 0 : printf("ERROR: !(poLayerFeatSRS->IsSame("
3707 : "poSQLFeatSRS)).\n");
3708 0 : bRet = FALSE;
3709 : }
3710 : }
3711 : }
3712 : }
3713 : }
3714 : }
3715 : }
3716 :
3717 292 : DestroyFeatureAndNullify(poLayerFeat);
3718 292 : DestroyFeatureAndNullify(poSQLFeat);
3719 :
3720 292 : LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
3721 :
3722 : /* Try ResetReading(), GetNextFeature(), ResetReading(), GetNextFeature() */
3723 292 : poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), nullptr, nullptr));
3724 292 : if (poSQLLyr == nullptr)
3725 : {
3726 0 : printf("ERROR: ExecuteSQL(%s) failed at line %d "
3727 : "(but succeeded before).\n",
3728 : osSQL.c_str(), __LINE__);
3729 0 : bRet = FALSE;
3730 0 : return bRet;
3731 : }
3732 292 : LOG_ACTION(poSQLLyr->ResetReading());
3733 :
3734 292 : poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
3735 292 : if (poSQLFeat == nullptr && bGotFeature)
3736 : {
3737 0 : printf("ERROR: Should have got feature (1)\n");
3738 0 : bRet = FALSE;
3739 : }
3740 292 : DestroyFeatureAndNullify(poSQLFeat);
3741 :
3742 292 : LOG_ACTION(poSQLLyr->ResetReading());
3743 :
3744 292 : poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
3745 292 : if (poSQLFeat == nullptr && bGotFeature)
3746 : {
3747 0 : printf("ERROR: Should have got feature (2)\n");
3748 0 : bRet = FALSE;
3749 : }
3750 292 : DestroyFeatureAndNullify(poSQLFeat);
3751 :
3752 292 : LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
3753 :
3754 : /* Return an empty layer */
3755 : osSQL.Printf("SELECT * FROM %s WHERE 0 = 1",
3756 292 : GetLayerNameForSQL(poDS, poLayer->GetName()));
3757 :
3758 292 : poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), nullptr, nullptr));
3759 292 : if (poSQLLyr)
3760 : {
3761 292 : poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
3762 292 : if (poSQLFeat != nullptr)
3763 : {
3764 0 : bRet = FALSE;
3765 0 : printf("ERROR: ExecuteSQL() should have returned "
3766 : "a layer without features.\n");
3767 : }
3768 292 : DestroyFeatureAndNullify(poSQLFeat);
3769 :
3770 292 : LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
3771 : }
3772 : else
3773 : {
3774 0 : printf("ERROR: ExecuteSQL() should have returned a non-NULL result.\n");
3775 0 : bRet = FALSE;
3776 : }
3777 :
3778 : // Test that installing a spatial filter on an empty layer at ExecuteSQL()
3779 : // does not raise an error
3780 : osSQL.Printf("SELECT * FROM %s WHERE 0 = 1",
3781 292 : GetLayerNameForSQL(poDS, poLayer->GetName()));
3782 :
3783 584 : OGRLinearRing oRing;
3784 292 : oRing.setPoint(0, 0, 0);
3785 292 : oRing.setPoint(1, 0, 1);
3786 292 : oRing.setPoint(2, 1, 1);
3787 292 : oRing.setPoint(3, 1, 0);
3788 292 : oRing.setPoint(4, 0, 0);
3789 :
3790 292 : OGRPolygon oPoly;
3791 292 : oPoly.addRing(&oRing);
3792 :
3793 292 : CPLErrorReset();
3794 292 : if (poLayer->GetLayerDefn()->GetGeomFieldCount() == 0)
3795 : {
3796 74 : CPLPushErrorHandler(CPLQuietErrorHandler);
3797 74 : poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), &oPoly, nullptr));
3798 74 : CPLPopErrorHandler();
3799 74 : if (poSQLLyr)
3800 : {
3801 0 : printf("WARNING: ExecuteSQL() with a spatial filter on a "
3802 : "non-spatial layer should have triggered an error.\n");
3803 : }
3804 : }
3805 : else
3806 : {
3807 218 : poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), &oPoly, nullptr));
3808 218 : if (CPLGetLastErrorType() == CE_Failure &&
3809 0 : poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
3810 : {
3811 0 : bRet = FALSE;
3812 0 : printf("ERROR: ExecuteSQL() triggered an unexpected error.\n");
3813 : }
3814 218 : if (!poSQLLyr)
3815 : {
3816 0 : printf("ERROR: ExecuteSQL() should have returned a non-NULL "
3817 : "result.\n");
3818 0 : bRet = FALSE;
3819 : }
3820 : }
3821 292 : if (poSQLLyr)
3822 : {
3823 218 : CPLErrorReset();
3824 218 : poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
3825 218 : if (CPLGetLastErrorType() == CE_Failure)
3826 : {
3827 0 : bRet = FALSE;
3828 0 : printf("ERROR: GetNextFeature() triggered an unexpected error.\n");
3829 : }
3830 218 : if (poSQLFeat != nullptr)
3831 : {
3832 0 : bRet = FALSE;
3833 0 : printf("ERROR: ExecuteSQL() should have returned "
3834 : "a layer without features.\n");
3835 : }
3836 218 : DestroyFeatureAndNullify(poSQLFeat);
3837 218 : LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
3838 : }
3839 :
3840 292 : if (bRet && bVerbose)
3841 292 : printf("INFO: TestLayerSQL passed.\n");
3842 :
3843 292 : return bRet;
3844 : }
3845 :
3846 : /************************************************************************/
3847 : /* CountFeaturesUsingArrowStream() */
3848 : /************************************************************************/
3849 :
3850 1296 : static int64_t CountFeaturesUsingArrowStream(OGRLayer *poLayer,
3851 : int64_t nExpectedFID,
3852 : int64_t nUnexpectedFID, bool &bOK)
3853 : {
3854 : struct ArrowArrayStream stream;
3855 1296 : if (!LOG_ACTION(poLayer->GetArrowStream(&stream)))
3856 : {
3857 0 : printf("ERROR: GetArrowStream() failed\n");
3858 0 : return -1;
3859 : }
3860 : struct ArrowSchema schema;
3861 1296 : if (stream.get_schema(&stream, &schema) != 0)
3862 : {
3863 0 : printf("ERROR: stream.get_schema() failed\n");
3864 0 : stream.release(&stream);
3865 0 : return -1;
3866 : }
3867 1296 : int iFIDColumn = -1;
3868 3888 : if (schema.n_children > 0 &&
3869 1296 : (strcmp(schema.children[0]->name, "OGC_FID") == 0 ||
3870 3152 : strcmp(schema.children[0]->name, poLayer->GetFIDColumn()) == 0) &&
3871 1268 : strcmp(schema.children[0]->format, "l") == 0)
3872 : {
3873 1268 : iFIDColumn = 0;
3874 : }
3875 1296 : schema.release(&schema);
3876 1296 : int64_t nFeatureCountFiltered = 0;
3877 1296 : bool bExpectedFIDFound = false;
3878 1296 : bool bUnexpectedFIDFound = false;
3879 : while (true)
3880 : {
3881 : struct ArrowArray array;
3882 2231 : if (stream.get_next(&stream, &array) != 0)
3883 : {
3884 0 : printf("ERROR: stream.get_next() is NULL\n");
3885 0 : stream.release(&stream);
3886 0 : return -1;
3887 : }
3888 2231 : if (!array.release)
3889 1296 : break;
3890 935 : if (iFIDColumn >= 0 && (nExpectedFID >= 0 || nUnexpectedFID >= 0))
3891 : {
3892 427 : const int64_t *panIds =
3893 427 : static_cast<const int64_t *>(
3894 427 : array.children[iFIDColumn]->buffers[1]) +
3895 427 : array.children[iFIDColumn]->offset;
3896 3222 : for (int64_t i = 0; i < array.length; ++i)
3897 : {
3898 2795 : if (nExpectedFID >= 0 && panIds[i] == nExpectedFID)
3899 427 : bExpectedFIDFound = true;
3900 2795 : if (nUnexpectedFID >= 0 && panIds[i] == nUnexpectedFID)
3901 0 : bUnexpectedFIDFound = true;
3902 : }
3903 : }
3904 935 : nFeatureCountFiltered += array.length;
3905 935 : array.release(&array);
3906 935 : }
3907 1296 : if (iFIDColumn >= 0)
3908 : {
3909 1268 : if (nExpectedFID >= 0 && !bExpectedFIDFound)
3910 : {
3911 0 : bOK = false;
3912 0 : printf("ERROR: expected to find feature of id %" PRId64
3913 : ", but did not get it\n",
3914 : nExpectedFID);
3915 : }
3916 1268 : if (nUnexpectedFID >= 0 && bUnexpectedFIDFound)
3917 : {
3918 0 : bOK = false;
3919 0 : printf("ERROR: expected *not* to find feature of id %" PRId64
3920 : ", but did get it\n",
3921 : nUnexpectedFID);
3922 : }
3923 : }
3924 1296 : stream.release(&stream);
3925 1296 : return nFeatureCountFiltered;
3926 : }
3927 :
3928 : /************************************************************************/
3929 : /* TestLayerGetArrowStream() */
3930 : /************************************************************************/
3931 :
3932 302 : static int TestLayerGetArrowStream(OGRLayer *poLayer)
3933 : {
3934 302 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
3935 302 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
3936 302 : LOG_ACTION(poLayer->ResetReading());
3937 :
3938 : struct ArrowArrayStream stream;
3939 302 : if (!LOG_ACTION(poLayer->GetArrowStream(&stream)))
3940 : {
3941 0 : printf("ERROR: GetArrowStream() failed\n");
3942 0 : return false;
3943 : }
3944 :
3945 302 : if (!stream.release)
3946 : {
3947 0 : printf("ERROR: stream.release is NULL\n");
3948 0 : return false;
3949 : }
3950 :
3951 : struct ArrowSchema schema;
3952 302 : if (stream.get_schema(&stream, &schema) != 0)
3953 : {
3954 0 : printf("ERROR: stream.get_schema() failed\n");
3955 0 : stream.release(&stream);
3956 0 : return false;
3957 : }
3958 :
3959 302 : if (!schema.release)
3960 : {
3961 0 : printf("ERROR: schema.release is NULL\n");
3962 0 : stream.release(&stream);
3963 0 : return false;
3964 : }
3965 :
3966 302 : if (strcmp(schema.format, "+s") != 0)
3967 : {
3968 0 : printf("ERROR: expected schema.format to be '+s'. Got '%s'\n",
3969 : schema.format);
3970 0 : schema.release(&schema);
3971 0 : stream.release(&stream);
3972 0 : return false;
3973 : }
3974 :
3975 302 : int64_t nFeatureCount = 0;
3976 : while (true)
3977 : {
3978 : struct ArrowArray array;
3979 594 : if (stream.get_next(&stream, &array) != 0)
3980 : {
3981 0 : printf("ERROR: stream.get_next() is NULL\n");
3982 0 : schema.release(&schema);
3983 0 : stream.release(&stream);
3984 0 : return false;
3985 : }
3986 594 : if (array.release == nullptr)
3987 : {
3988 302 : break;
3989 : }
3990 :
3991 292 : if (array.n_children != schema.n_children)
3992 : {
3993 0 : printf("ERROR: expected array.n_children (=%d) to be "
3994 : "schema.n_children (=%d)\n",
3995 0 : int(array.n_children), int(schema.n_children));
3996 0 : array.release(&array);
3997 0 : schema.release(&schema);
3998 0 : stream.release(&stream);
3999 0 : return false;
4000 : }
4001 :
4002 292 : int bRet = true;
4003 3625 : for (int i = 0; i < array.n_children; ++i)
4004 : {
4005 3333 : if (array.children[i]->length != array.length)
4006 : {
4007 0 : bRet = false;
4008 0 : printf("ERROR: expected array.children[i]->length (=%d) to be "
4009 : "array.length (=%d)\n",
4010 0 : int(array.children[i]->length), int(array.length));
4011 : }
4012 : }
4013 292 : if (!bRet)
4014 : {
4015 0 : array.release(&array);
4016 0 : schema.release(&schema);
4017 0 : stream.release(&stream);
4018 0 : return false;
4019 : }
4020 :
4021 292 : nFeatureCount += array.length;
4022 :
4023 292 : array.release(&array);
4024 :
4025 292 : if (array.release)
4026 : {
4027 0 : printf("ERROR: array.release should be NULL after release\n");
4028 0 : schema.release(&schema);
4029 0 : stream.release(&stream);
4030 0 : return false;
4031 : }
4032 292 : }
4033 :
4034 302 : bool bRet = true;
4035 : // We are a bit in non-specified behavior below by calling get_next()
4036 : // after end of iteration.
4037 : {
4038 : struct ArrowArray array;
4039 302 : if (stream.get_next(&stream, &array) == 0)
4040 : {
4041 302 : if (array.length != 0)
4042 : {
4043 0 : bRet = false;
4044 0 : printf("ERROR: get_next() return an array with length != 0 "
4045 : "after end of iteration\n");
4046 : }
4047 302 : if (array.release)
4048 0 : array.release(&array);
4049 : }
4050 : }
4051 :
4052 302 : schema.release(&schema);
4053 302 : if (schema.release)
4054 : {
4055 0 : printf("ERROR: schema.release should be NULL after release\n");
4056 0 : stream.release(&stream);
4057 0 : return false;
4058 : }
4059 :
4060 302 : stream.release(&stream);
4061 302 : if (stream.release)
4062 : {
4063 0 : printf("ERROR: stream.release should be NULL after release\n");
4064 0 : return false;
4065 : }
4066 :
4067 302 : const int64_t nFCClassic = poLayer->GetFeatureCount(true);
4068 302 : if (nFeatureCount != nFCClassic)
4069 : {
4070 0 : printf("ERROR: GetArrowStream() returned %" PRId64
4071 : " features, whereas GetFeatureCount() returned %" PRId64 "\n",
4072 : nFeatureCount, nFCClassic);
4073 0 : bRet = false;
4074 : }
4075 :
4076 : {
4077 302 : LOG_ACTION(poLayer->SetAttributeFilter("1=1"));
4078 : const auto nFeatureCountFiltered =
4079 302 : CountFeaturesUsingArrowStream(poLayer, -1, -1, bRet);
4080 302 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
4081 302 : if (nFeatureCount != nFeatureCountFiltered)
4082 : {
4083 0 : printf("ERROR: GetArrowStream() with 1=1 filter returned %" PRId64
4084 : " features, whereas %" PRId64 " expected\n",
4085 : nFeatureCountFiltered, nFeatureCount);
4086 0 : bRet = false;
4087 : }
4088 : }
4089 :
4090 : {
4091 302 : LOG_ACTION(poLayer->SetAttributeFilter("1=0"));
4092 : const auto nFeatureCountFiltered =
4093 302 : CountFeaturesUsingArrowStream(poLayer, -1, -1, bRet);
4094 302 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
4095 302 : if (nFeatureCountFiltered != 0)
4096 : {
4097 0 : printf("ERROR: GetArrowStream() with 1=0 filter returned %" PRId64
4098 : " features, whereas 0 expected\n",
4099 : nFeatureCountFiltered);
4100 0 : bRet = false;
4101 : }
4102 : }
4103 :
4104 302 : std::unique_ptr<OGRFeature> poTargetFeature;
4105 604 : std::string osInclusiveFilter;
4106 302 : std::string osExclusiveFilter;
4107 302 : if (GetAttributeFilters(poLayer, poTargetFeature, osInclusiveFilter,
4108 : osExclusiveFilter))
4109 : {
4110 : {
4111 256 : LOG_ACTION(poLayer->SetAttributeFilter(osInclusiveFilter.c_str()));
4112 256 : const auto nFeatureCountFiltered = CountFeaturesUsingArrowStream(
4113 256 : poLayer, poTargetFeature->GetFID(), -1, bRet);
4114 256 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
4115 256 : if (nFeatureCountFiltered == 0)
4116 : {
4117 0 : printf(
4118 : "ERROR: GetArrowStream() with %s filter returned %" PRId64
4119 : " features, whereas at least one expected\n",
4120 : osInclusiveFilter.c_str(), nFeatureCountFiltered);
4121 0 : bRet = false;
4122 : }
4123 256 : else if (bVerbose)
4124 : {
4125 256 : printf("INFO: Attribute filter inclusion with GetArrowStream "
4126 : "seems to work.\n");
4127 : }
4128 : }
4129 :
4130 : {
4131 256 : LOG_ACTION(poLayer->SetAttributeFilter(osExclusiveFilter.c_str()));
4132 : const auto nFeatureCountFiltered =
4133 256 : CountFeaturesUsingArrowStream(poLayer, -1, -1, bRet);
4134 256 : LOG_ACTION(poLayer->SetAttributeFilter(nullptr));
4135 256 : if (nFeatureCountFiltered >= nFCClassic)
4136 : {
4137 0 : printf(
4138 : "ERROR: GetArrowStream() with %s filter returned %" PRId64
4139 : " features, whereas less than %" PRId64 " expected\n",
4140 : osExclusiveFilter.c_str(), nFeatureCountFiltered,
4141 : nFCClassic);
4142 0 : bRet = false;
4143 : }
4144 256 : else if (bVerbose)
4145 : {
4146 256 : printf("INFO: Attribute filter exclusion with GetArrowStream "
4147 : "seems to work.\n");
4148 : }
4149 : }
4150 :
4151 256 : auto poGeom = poTargetFeature->GetGeometryRef();
4152 256 : if (poGeom && !poGeom->IsEmpty())
4153 : {
4154 180 : OGREnvelope sEnvelope;
4155 180 : poGeom->getEnvelope(&sEnvelope);
4156 :
4157 180 : OGREnvelope sLayerExtent;
4158 180 : double epsilon = 10.0;
4159 180 : if (LOG_ACTION(poLayer->TestCapability(OLCFastGetExtent)) &&
4160 126 : LOG_ACTION(poLayer->GetExtent(&sLayerExtent)) == OGRERR_NONE &&
4161 407 : sLayerExtent.MinX < sLayerExtent.MaxX &&
4162 101 : sLayerExtent.MinY < sLayerExtent.MaxY)
4163 : {
4164 196 : epsilon = std::min(sLayerExtent.MaxX - sLayerExtent.MinX,
4165 98 : sLayerExtent.MaxY - sLayerExtent.MinY) /
4166 : 10.0;
4167 : }
4168 :
4169 : /* -------------------------------------------------------------------- */
4170 : /* Construct inclusive filter. */
4171 : /* -------------------------------------------------------------------- */
4172 :
4173 360 : OGRLinearRing oRing;
4174 180 : oRing.setPoint(0, sEnvelope.MinX - 2 * epsilon,
4175 180 : sEnvelope.MinY - 2 * epsilon);
4176 180 : oRing.setPoint(1, sEnvelope.MinX - 2 * epsilon,
4177 180 : sEnvelope.MaxY + 1 * epsilon);
4178 180 : oRing.setPoint(2, sEnvelope.MaxX + 1 * epsilon,
4179 180 : sEnvelope.MaxY + 1 * epsilon);
4180 180 : oRing.setPoint(3, sEnvelope.MaxX + 1 * epsilon,
4181 180 : sEnvelope.MinY - 2 * epsilon);
4182 180 : oRing.setPoint(4, sEnvelope.MinX - 2 * epsilon,
4183 180 : sEnvelope.MinY - 2 * epsilon);
4184 :
4185 360 : OGRPolygon oInclusiveFilter;
4186 180 : oInclusiveFilter.addRing(&oRing);
4187 :
4188 180 : LOG_ACTION(poLayer->SetSpatialFilter(&oInclusiveFilter));
4189 180 : const auto nFeatureCountFiltered = CountFeaturesUsingArrowStream(
4190 180 : poLayer, poTargetFeature->GetFID(), -1, bRet);
4191 180 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
4192 180 : if (nFeatureCountFiltered == 0)
4193 : {
4194 0 : printf("ERROR: GetArrowStream() with inclusive spatial filter "
4195 : "returned %" PRId64
4196 : " features, whereas at least 1 expected\n",
4197 : nFeatureCountFiltered);
4198 0 : bRet = false;
4199 : }
4200 180 : else if (bVerbose)
4201 : {
4202 180 : printf("INFO: Spatial filter inclusion with GetArrowStream "
4203 : "seems to work.\n");
4204 : }
4205 : }
4206 : }
4207 :
4208 302 : if (bRet && bVerbose)
4209 302 : printf("INFO: TestLayerGetArrowStream passed.\n");
4210 :
4211 302 : return bRet;
4212 : }
4213 :
4214 : /************************************************************************/
4215 : /* TestOGRLayer() */
4216 : /************************************************************************/
4217 :
4218 302 : static int TestOGRLayer(GDALDataset *poDS, OGRLayer *poLayer, int bIsSQLLayer)
4219 :
4220 : {
4221 302 : int bRet = TRUE;
4222 :
4223 : // Check that pszDomain == nullptr doesn't crash
4224 302 : poLayer->GetMetadata(nullptr);
4225 302 : poLayer->GetMetadataItem("", nullptr);
4226 :
4227 : /* -------------------------------------------------------------------- */
4228 : /* Verify that there is no spatial filter in place by default. */
4229 : /* -------------------------------------------------------------------- */
4230 302 : if (LOG_ACTION(poLayer->GetSpatialFilter()) != nullptr)
4231 : {
4232 0 : printf("WARN: Spatial filter in place by default on layer %s.\n",
4233 0 : poLayer->GetName());
4234 0 : LOG_ACTION(poLayer->SetSpatialFilter(nullptr));
4235 : }
4236 :
4237 : /* -------------------------------------------------------------------- */
4238 : /* Basic tests. */
4239 : /* -------------------------------------------------------------------- */
4240 302 : bRet &= TestBasic(poDS, poLayer);
4241 :
4242 : /* -------------------------------------------------------------------- */
4243 : /* Test feature count accuracy. */
4244 : /* -------------------------------------------------------------------- */
4245 302 : bRet &= TestOGRLayerFeatureCount(poDS, poLayer, bIsSQLLayer);
4246 :
4247 : /* -------------------------------------------------------------------- */
4248 : /* Test spatial filtering */
4249 : /* -------------------------------------------------------------------- */
4250 302 : bRet &= TestSpatialFilter(poLayer);
4251 :
4252 : /* -------------------------------------------------------------------- */
4253 : /* Test attribute filtering */
4254 : /* -------------------------------------------------------------------- */
4255 302 : bRet &= TestAttributeFilter(poDS, poLayer);
4256 :
4257 : /* -------------------------------------------------------------------- */
4258 : /* Test GetExtent() */
4259 : /* -------------------------------------------------------------------- */
4260 302 : bRet &= TestGetExtent(poLayer);
4261 :
4262 : /* -------------------------------------------------------------------- */
4263 : /* Test GetArrowStream() interface */
4264 : /* -------------------------------------------------------------------- */
4265 302 : bRet &= TestLayerGetArrowStream(poLayer);
4266 :
4267 : /* -------------------------------------------------------------------- */
4268 : /* Test random reading. */
4269 : /* -------------------------------------------------------------------- */
4270 302 : bRet &= TestOGRLayerRandomRead(poLayer);
4271 :
4272 : /* -------------------------------------------------------------------- */
4273 : /* Test SetNextByIndex. */
4274 : /* -------------------------------------------------------------------- */
4275 302 : bRet &= TestOGRLayerSetNextByIndex(poLayer);
4276 :
4277 : /* -------------------------------------------------------------------- */
4278 : /* Test delete feature. */
4279 : /* -------------------------------------------------------------------- */
4280 302 : if (LOG_ACTION(poLayer->TestCapability(OLCDeleteFeature)))
4281 : {
4282 31 : bRet &= TestOGRLayerDeleteAndCreateFeature(poLayer);
4283 : }
4284 :
4285 : /* -------------------------------------------------------------------- */
4286 : /* Test random writing. */
4287 : /* -------------------------------------------------------------------- */
4288 302 : if (LOG_ACTION(poLayer->TestCapability(OLCRandomWrite)))
4289 : {
4290 31 : bRet &= TestOGRLayerRandomWrite(poLayer);
4291 : }
4292 :
4293 : /* -------------------------------------------------------------------- */
4294 : /* Test OLCIgnoreFields. */
4295 : /* -------------------------------------------------------------------- */
4296 302 : if (LOG_ACTION(poLayer->TestCapability(OLCIgnoreFields)))
4297 : {
4298 132 : bRet &= TestOGRLayerIgnoreFields(poLayer);
4299 : }
4300 :
4301 : /* -------------------------------------------------------------------- */
4302 : /* Test UTF-8 reporting */
4303 : /* -------------------------------------------------------------------- */
4304 302 : bRet &= TestOGRLayerUTF8(poLayer);
4305 :
4306 : /* -------------------------------------------------------------------- */
4307 : /* Test TestTransactions() */
4308 : /* -------------------------------------------------------------------- */
4309 302 : if (LOG_ACTION(poLayer->TestCapability(OLCSequentialWrite)))
4310 : {
4311 46 : bRet &= TestTransactions(poLayer);
4312 : }
4313 :
4314 : /* -------------------------------------------------------------------- */
4315 : /* Test error conditions. */
4316 : /* -------------------------------------------------------------------- */
4317 302 : bRet &= TestLayerErrorConditions(poLayer);
4318 :
4319 : /* -------------------------------------------------------------------- */
4320 : /* Test some SQL. */
4321 : /* -------------------------------------------------------------------- */
4322 302 : if (!bIsSQLLayer)
4323 292 : bRet &= TestLayerSQL(poDS, poLayer);
4324 :
4325 302 : return bRet;
4326 : }
4327 :
4328 : /************************************************************************/
4329 : /* TestInterleavedReading() */
4330 : /************************************************************************/
4331 :
4332 20 : static int TestInterleavedReading(const char *pszDataSourceIn,
4333 : char **papszLayersIn)
4334 : {
4335 20 : int bRet = TRUE;
4336 20 : GDALDataset *poDS2 = nullptr;
4337 20 : OGRLayer *poLayer1 = nullptr;
4338 20 : OGRLayer *poLayer2 = nullptr;
4339 20 : OGRFeature *poFeature11_Ref = nullptr;
4340 20 : OGRFeature *poFeature12_Ref = nullptr;
4341 20 : OGRFeature *poFeature21_Ref = nullptr;
4342 20 : OGRFeature *poFeature22_Ref = nullptr;
4343 20 : OGRFeature *poFeature11 = nullptr;
4344 20 : OGRFeature *poFeature12 = nullptr;
4345 20 : OGRFeature *poFeature21 = nullptr;
4346 20 : OGRFeature *poFeature22 = nullptr;
4347 :
4348 : /* Check that we have 2 layers with at least 2 features */
4349 20 : GDALDataset *poDS = LOG_ACTION(static_cast<GDALDataset *>(GDALOpenEx(
4350 : pszDataSourceIn, GDAL_OF_VECTOR, nullptr, papszOpenOptions, nullptr)));
4351 20 : if (poDS == nullptr)
4352 : {
4353 0 : if (bVerbose)
4354 : {
4355 0 : printf("INFO: Skipping TestInterleavedReading(). "
4356 : "Cannot reopen datasource\n");
4357 : }
4358 0 : goto bye;
4359 : }
4360 :
4361 20 : poLayer1 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[0])
4362 : : poDS->GetLayer(0));
4363 20 : poLayer2 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[1])
4364 : : poDS->GetLayer(1));
4365 20 : if (poLayer1 == nullptr || poLayer2 == nullptr ||
4366 54 : LOG_ACTION(poLayer1->GetFeatureCount()) < 2 ||
4367 14 : LOG_ACTION(poLayer2->GetFeatureCount()) < 2)
4368 : {
4369 9 : if (bVerbose)
4370 : {
4371 9 : printf("INFO: Skipping TestInterleavedReading(). "
4372 : "Test conditions are not met\n");
4373 : }
4374 9 : goto bye;
4375 : }
4376 :
4377 : /* Test normal reading */
4378 11 : LOG_ACTION(GDALClose(poDS));
4379 11 : poDS = LOG_ACTION(static_cast<GDALDataset *>(GDALOpenEx(
4380 : pszDataSourceIn, GDAL_OF_VECTOR, nullptr, papszOpenOptions, nullptr)));
4381 11 : poDS2 = LOG_ACTION(static_cast<GDALDataset *>(GDALOpenEx(
4382 : pszDataSourceIn, GDAL_OF_VECTOR, nullptr, papszOpenOptions, nullptr)));
4383 11 : if (poDS == nullptr || poDS2 == nullptr)
4384 : {
4385 0 : if (bVerbose)
4386 : {
4387 0 : printf("INFO: Skipping TestInterleavedReading(). "
4388 : "Cannot reopen datasource\n");
4389 : }
4390 0 : goto bye;
4391 : }
4392 :
4393 11 : poLayer1 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[0])
4394 : : poDS->GetLayer(0));
4395 11 : poLayer2 = LOG_ACTION(papszLayersIn ? poDS->GetLayerByName(papszLayersIn[1])
4396 : : poDS->GetLayer(1));
4397 11 : if (poLayer1 == nullptr || poLayer2 == nullptr)
4398 : {
4399 0 : printf("ERROR: Skipping TestInterleavedReading(). "
4400 : "Test conditions are not met\n");
4401 0 : bRet = FALSE;
4402 0 : goto bye;
4403 : }
4404 :
4405 11 : poFeature11_Ref = LOG_ACTION(poLayer1->GetNextFeature());
4406 11 : poFeature12_Ref = LOG_ACTION(poLayer1->GetNextFeature());
4407 11 : poFeature21_Ref = LOG_ACTION(poLayer2->GetNextFeature());
4408 11 : poFeature22_Ref = LOG_ACTION(poLayer2->GetNextFeature());
4409 11 : if (poFeature11_Ref == nullptr || poFeature12_Ref == nullptr ||
4410 11 : poFeature21_Ref == nullptr || poFeature22_Ref == nullptr)
4411 : {
4412 0 : printf("ERROR: TestInterleavedReading() failed: poFeature11_Ref=%p, "
4413 : "poFeature12_Ref=%p, poFeature21_Ref=%p, poFeature22_Ref=%p\n",
4414 : poFeature11_Ref, poFeature12_Ref, poFeature21_Ref,
4415 : poFeature22_Ref);
4416 0 : bRet = FALSE;
4417 0 : goto bye;
4418 : }
4419 :
4420 : /* Test interleaved reading */
4421 11 : poLayer1 =
4422 11 : LOG_ACTION(papszLayersIn ? poDS2->GetLayerByName(papszLayersIn[0])
4423 : : poDS2->GetLayer(0));
4424 11 : poLayer2 =
4425 11 : LOG_ACTION(papszLayersIn ? poDS2->GetLayerByName(papszLayersIn[1])
4426 : : poDS2->GetLayer(1));
4427 11 : if (poLayer1 == nullptr || poLayer2 == nullptr)
4428 : {
4429 0 : printf("ERROR: Skipping TestInterleavedReading(). "
4430 : "Test conditions are not met\n");
4431 0 : bRet = FALSE;
4432 0 : goto bye;
4433 : }
4434 :
4435 11 : poFeature11 = LOG_ACTION(poLayer1->GetNextFeature());
4436 11 : poFeature21 = LOG_ACTION(poLayer2->GetNextFeature());
4437 11 : poFeature12 = LOG_ACTION(poLayer1->GetNextFeature());
4438 11 : poFeature22 = LOG_ACTION(poLayer2->GetNextFeature());
4439 :
4440 11 : if (poFeature11 == nullptr || poFeature21 == nullptr ||
4441 11 : poFeature12 == nullptr || poFeature22 == nullptr)
4442 : {
4443 0 : printf("ERROR: TestInterleavedReading() failed: poFeature11=%p, "
4444 : "poFeature21=%p, poFeature12=%p, poFeature22=%p\n",
4445 : poFeature11, poFeature21, poFeature12, poFeature22);
4446 0 : bRet = FALSE;
4447 0 : goto bye;
4448 : }
4449 :
4450 11 : if (poFeature12->Equal(poFeature11))
4451 : {
4452 0 : printf("WARN: TestInterleavedReading() failed: poFeature12 == "
4453 : "poFeature11. "
4454 : "The datasource resets the layer reading when interleaved "
4455 : "layer reading pattern is detected. Acceptable but could be "
4456 : "improved\n");
4457 0 : goto bye;
4458 : }
4459 :
4460 : /* We cannot directly compare the feature as they don't share */
4461 : /* the same (pointer) layer definition, so just compare FIDs */
4462 11 : if (poFeature12_Ref->GetFID() != poFeature12->GetFID())
4463 : {
4464 0 : printf("ERROR: TestInterleavedReading() failed: "
4465 : "poFeature12_Ref != poFeature12\n");
4466 0 : poFeature12_Ref->DumpReadable(stdout, nullptr);
4467 0 : poFeature12->DumpReadable(stdout, nullptr);
4468 0 : bRet = FALSE;
4469 0 : goto bye;
4470 : }
4471 :
4472 11 : if (bVerbose)
4473 : {
4474 11 : printf("INFO: TestInterleavedReading() successful.\n");
4475 : }
4476 :
4477 0 : bye:
4478 20 : DestroyFeatureAndNullify(poFeature11_Ref);
4479 20 : DestroyFeatureAndNullify(poFeature12_Ref);
4480 20 : DestroyFeatureAndNullify(poFeature21_Ref);
4481 20 : DestroyFeatureAndNullify(poFeature22_Ref);
4482 20 : DestroyFeatureAndNullify(poFeature11);
4483 20 : DestroyFeatureAndNullify(poFeature21);
4484 20 : DestroyFeatureAndNullify(poFeature12);
4485 20 : DestroyFeatureAndNullify(poFeature22);
4486 20 : if (poDS != nullptr)
4487 20 : LOG_ACTION(GDALClose(poDS));
4488 20 : if (poDS2 != nullptr)
4489 11 : LOG_ACTION(GDALClose(poDS2));
4490 20 : return bRet;
4491 : }
4492 :
4493 : /************************************************************************/
4494 : /* TestDSErrorConditions() */
4495 : /************************************************************************/
4496 :
4497 104 : static int TestDSErrorConditions(GDALDataset *poDS)
4498 : {
4499 104 : int bRet = TRUE;
4500 : OGRLayer *poLyr;
4501 :
4502 104 : CPLPushErrorHandler(CPLQuietErrorHandler);
4503 :
4504 104 : if (LOG_ACTION(poDS->TestCapability("fake_capability")))
4505 : {
4506 0 : printf("ERROR: TestCapability(\"fake_capability\") "
4507 : "should have returned FALSE\n");
4508 0 : bRet = FALSE;
4509 0 : goto bye;
4510 : }
4511 :
4512 104 : if (LOG_ACTION(poDS->GetLayer(-1)) != nullptr)
4513 : {
4514 0 : printf("ERROR: GetLayer(-1) should have returned NULL\n");
4515 0 : bRet = FALSE;
4516 0 : goto bye;
4517 : }
4518 :
4519 104 : if (LOG_ACTION(poDS->GetLayer(poDS->GetLayerCount())) != nullptr)
4520 : {
4521 0 : printf("ERROR: GetLayer(poDS->GetLayerCount()) should have "
4522 : "returned NULL\n");
4523 0 : bRet = FALSE;
4524 0 : goto bye;
4525 : }
4526 :
4527 104 : if (LOG_ACTION(poDS->GetLayerByName("non_existing_layer")) != nullptr)
4528 : {
4529 0 : printf("ERROR: GetLayerByName(\"non_existing_layer\") should have "
4530 : "returned NULL\n");
4531 0 : bRet = FALSE;
4532 0 : goto bye;
4533 : }
4534 :
4535 : poLyr =
4536 104 : LOG_ACTION(poDS->ExecuteSQL("a fake SQL command", nullptr, nullptr));
4537 104 : if (poLyr != nullptr)
4538 : {
4539 0 : LOG_ACTION(poDS->ReleaseResultSet(poLyr));
4540 0 : printf("ERROR: ExecuteSQL(\"a fake SQL command\") should have "
4541 : "returned NULL\n");
4542 0 : bRet = FALSE;
4543 0 : goto bye;
4544 : }
4545 :
4546 104 : bye:
4547 104 : CPLPopErrorHandler();
4548 104 : return bRet;
4549 : }
4550 :
4551 : /************************************************************************/
4552 : /* TestVirtualIO() */
4553 : /************************************************************************/
4554 :
4555 104 : static int TestVirtualIO(GDALDataset *poDS)
4556 : {
4557 104 : int bRet = TRUE;
4558 :
4559 104 : if (STARTS_WITH(poDS->GetDescription(), "/vsimem/"))
4560 0 : return TRUE;
4561 :
4562 : VSIStatBufL sStat;
4563 104 : if (!(VSIStatL(poDS->GetDescription(), &sStat) == 0))
4564 13 : return TRUE;
4565 :
4566 : // Don't try with ODBC (will avoid a useless error message in ogr_odbc.py)
4567 182 : if (poDS->GetDriver() != nullptr &&
4568 91 : EQUAL(poDS->GetDriver()->GetDescription(), "ODBC"))
4569 : {
4570 0 : return TRUE;
4571 : }
4572 :
4573 182 : const CPLStringList aosFileList(LOG_ACTION(poDS->GetFileList()));
4574 182 : CPLString osPath;
4575 91 : int bAllPathIdentical = TRUE;
4576 1282 : for (const char *pszFilename : aosFileList)
4577 : {
4578 1198 : if (pszFilename == aosFileList[0])
4579 91 : osPath = CPLGetPath(pszFilename);
4580 1107 : else if (strcmp(osPath, CPLGetPath(pszFilename)) != 0)
4581 : {
4582 7 : bAllPathIdentical = FALSE;
4583 7 : break;
4584 : }
4585 : }
4586 91 : CPLString osVirtPath;
4587 91 : if (bAllPathIdentical && aosFileList.size() > 1)
4588 : {
4589 : osVirtPath =
4590 25 : CPLFormFilename("/vsimem", CPLGetFilename(osPath), nullptr);
4591 25 : VSIMkdir(osVirtPath, 0666);
4592 : }
4593 : else
4594 66 : osVirtPath = "/vsimem";
4595 :
4596 1310 : for (const char *pszFilename : aosFileList)
4597 : {
4598 : const char *pszDestFile =
4599 1219 : CPLFormFilename(osVirtPath, CPLGetFilename(pszFilename), nullptr);
4600 : /* CPLDebug("test_ogrsf", "Copying %s to %s", pszFilename, pszDestFile);
4601 : */
4602 1219 : CPLCopyFile(pszDestFile, pszFilename);
4603 : }
4604 :
4605 : const char *pszVirtFile;
4606 91 : if (VSI_ISREG(sStat.st_mode))
4607 82 : pszVirtFile = CPLFormFilename(
4608 82 : osVirtPath, CPLGetFilename(poDS->GetDescription()), nullptr);
4609 : else
4610 9 : pszVirtFile = osVirtPath;
4611 91 : CPLDebug("test_ogrsf", "Trying to open %s", pszVirtFile);
4612 91 : GDALDataset *poDS2 = LOG_ACTION(static_cast<GDALDataset *>(
4613 : GDALOpenEx(pszVirtFile, GDAL_OF_VECTOR, nullptr, nullptr, nullptr)));
4614 91 : if (poDS2 != nullptr)
4615 : {
4616 78 : if (poDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VIRTUALIO) == nullptr)
4617 : {
4618 0 : printf("WARNING: %s driver apparently supports VirtualIO "
4619 : "but does not declare it.\n",
4620 0 : poDS->GetDriver()->GetDescription());
4621 : }
4622 78 : if (poDS2->GetLayerCount() != poDS->GetLayerCount())
4623 : {
4624 1 : printf("WARNING: /vsimem dataset reports %d layers where as base "
4625 : "dataset reports %d layers.\n",
4626 1 : poDS2->GetLayerCount(), poDS->GetLayerCount());
4627 : }
4628 78 : GDALClose(poDS2);
4629 :
4630 78 : if (bVerbose && bRet)
4631 : {
4632 78 : printf("INFO: TestVirtualIO successful.\n");
4633 : }
4634 : }
4635 : else
4636 : {
4637 13 : if (poDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VIRTUALIO) != nullptr)
4638 : {
4639 10 : printf("WARNING: %s driver declares supporting VirtualIO but "
4640 : "test with /vsimem does not work. It might be a sign that "
4641 : "GetFileList() is not properly implemented.\n",
4642 10 : poDS->GetDriver()->GetDescription());
4643 : }
4644 : }
4645 :
4646 1310 : for (const char *pszFilename : aosFileList)
4647 : {
4648 1219 : VSIUnlink(
4649 : CPLFormFilename(osVirtPath, CPLGetFilename(pszFilename), nullptr));
4650 : }
4651 :
4652 91 : return bRet;
4653 : }
|