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