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