Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Extension SQL functions used by both SQLite dialect and GPKG driver
5 : * Author: Even Rouault, even dot rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2012-2022, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : /* WARNING: VERY IMPORTANT NOTE: This file MUST not be directly compiled as */
14 : /* a standalone object. It must be included from ogrsqlitevirtualogr.cpp */
15 : #ifndef COMPILATION_ALLOWED
16 : #error See comment in file
17 : #endif
18 :
19 : #include "gdal_alg.h"
20 : #include "gdal_priv.h"
21 : #include "ogr_geocoding.h"
22 :
23 : #include "ogrsqliteregexp.cpp" /* yes the .cpp file, to make it work on Windows with load_extension('gdalXX.dll') */
24 :
25 : #include <algorithm>
26 : #include <cassert>
27 : #include <cmath>
28 : #include <map>
29 :
30 : #include "ogr_swq.h"
31 :
32 : namespace
33 : {
34 : class OGRSQLiteExtensionData
35 : {
36 : #ifdef DEBUG
37 : void *pDummy = nullptr; /* to track memory leaks */
38 : #endif
39 :
40 : std::map<std::pair<int, int>, std::unique_ptr<OGRCoordinateTransformation>>
41 : // cppcheck-suppress unusedStructMember
42 : oCachedTransformsMap{};
43 : std::map<std::string, std::unique_ptr<GDALDataset>> oCachedDS{};
44 :
45 : void *hRegExpCache = nullptr;
46 :
47 : OGRGeocodingSessionH hGeocodingSession = nullptr;
48 :
49 : bool bCaseSensitiveLike = false;
50 :
51 : OGRSQLiteExtensionData(const OGRSQLiteExtensionData &) = delete;
52 : OGRSQLiteExtensionData &operator=(const OGRSQLiteExtensionData &) = delete;
53 :
54 : public:
55 : explicit OGRSQLiteExtensionData(sqlite3 *hDB);
56 : ~OGRSQLiteExtensionData();
57 :
58 : #ifdef DEFINE_OGRSQLiteExtensionData_GetTransform
59 : OGRCoordinateTransformation *GetTransform(int nSrcSRSId, int nDstSRSId);
60 : #endif
61 :
62 : GDALDataset *GetDataset(const char *pszDSName);
63 :
64 112 : OGRGeocodingSessionH GetGeocodingSession()
65 : {
66 112 : return hGeocodingSession;
67 : }
68 :
69 112 : void SetGeocodingSession(OGRGeocodingSessionH hGeocodingSessionIn)
70 : {
71 112 : hGeocodingSession = hGeocodingSessionIn;
72 112 : }
73 :
74 3601 : void SetRegExpCache(void *hRegExpCacheIn)
75 : {
76 3601 : hRegExpCache = hRegExpCacheIn;
77 3601 : }
78 :
79 4 : void SetCaseSensitiveLike(bool b)
80 : {
81 4 : bCaseSensitiveLike = b;
82 4 : }
83 :
84 221569 : bool GetCaseSensitiveLike() const
85 : {
86 221569 : return bCaseSensitiveLike;
87 : }
88 : };
89 :
90 : /************************************************************************/
91 : /* OGRSQLiteExtensionData() */
92 : /************************************************************************/
93 :
94 3601 : OGRSQLiteExtensionData::OGRSQLiteExtensionData(CPL_UNUSED sqlite3 *hDB)
95 : :
96 : #ifdef DEBUG
97 3601 : pDummy(CPLMalloc(1)),
98 : #endif
99 3601 : hRegExpCache(nullptr), hGeocodingSession(nullptr)
100 : {
101 3601 : }
102 :
103 : /************************************************************************/
104 : /* ~OGRSQLiteExtensionData() */
105 : /************************************************************************/
106 :
107 3599 : OGRSQLiteExtensionData::~OGRSQLiteExtensionData()
108 : {
109 : #ifdef DEBUG
110 3599 : CPLFree(pDummy);
111 : #endif
112 :
113 3599 : OGRSQLiteFreeRegExpCache(hRegExpCache);
114 :
115 3599 : OGRGeocodeDestroySession(hGeocodingSession);
116 3599 : }
117 :
118 : /************************************************************************/
119 : /* GetTransform() */
120 : /************************************************************************/
121 :
122 : #ifdef DEFINE_OGRSQLiteExtensionData_GetTransform
123 0 : OGRCoordinateTransformation *OGRSQLiteExtensionData::GetTransform(int nSrcSRSId,
124 : int nDstSRSId)
125 : {
126 0 : auto oIter = oCachedTransformsMap.find(std::pair(nSrcSRSId, nDstSRSId));
127 0 : if (oIter == oCachedTransformsMap.end())
128 : {
129 0 : std::unique_ptr<OGRCoordinateTransformation> poCT;
130 0 : OGRSpatialReference oSrcSRS, oDstSRS;
131 0 : oSrcSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
132 0 : oDstSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
133 0 : if (oSrcSRS.importFromEPSG(nSrcSRSId) == OGRERR_NONE &&
134 0 : oDstSRS.importFromEPSG(nDstSRSId) == OGRERR_NONE)
135 : {
136 0 : poCT.reset(OGRCreateCoordinateTransformation(&oSrcSRS, &oDstSRS));
137 : }
138 0 : oIter = oCachedTransformsMap
139 0 : .insert({std::pair(nSrcSRSId, nDstSRSId), std::move(poCT)})
140 : .first;
141 : }
142 0 : return oIter->second.get();
143 : }
144 : #endif
145 :
146 : /************************************************************************/
147 : /* GetDataset() */
148 : /************************************************************************/
149 :
150 15 : GDALDataset *OGRSQLiteExtensionData::GetDataset(const char *pszDSName)
151 : {
152 15 : auto oIter = oCachedDS.find(pszDSName);
153 15 : if (oIter != oCachedDS.end())
154 11 : return oIter->second.get();
155 :
156 : auto poDS = std::unique_ptr<GDALDataset>(
157 8 : GDALDataset::Open(pszDSName, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR));
158 4 : if (!poDS)
159 : {
160 0 : return nullptr;
161 : }
162 4 : oIter = oCachedDS.insert({pszDSName, std::move(poDS)}).first;
163 4 : return oIter->second.get();
164 : }
165 :
166 : } // namespace
167 :
168 : /************************************************************************/
169 : /* OGRSQLITE_gdal_get_pixel_value() */
170 : /************************************************************************/
171 :
172 17 : static void OGRSQLITE_gdal_get_pixel_value(sqlite3_context *pContext, int argc,
173 : sqlite3_value **argv)
174 : {
175 17 : if (!CPLTestBool(
176 : CPLGetConfigOption("OGR_SQLITE_ALLOW_EXTERNAL_ACCESS", "NO")))
177 : {
178 1 : CPLError(CE_Failure, CPLE_AppDefined,
179 : "gdal_get_pixel_value() SQL function not available "
180 : "if OGR_SQLITE_ALLOW_EXTERNAL_ACCESS configuration option "
181 : "is not set");
182 1 : sqlite3_result_null(pContext);
183 1 : return;
184 : }
185 :
186 16 : if (sqlite3_value_type(argv[0]) != SQLITE_TEXT)
187 : {
188 1 : CPLError(CE_Failure, CPLE_AppDefined,
189 : "Invalid arguments to gdal_get_layer_pixel_value()");
190 1 : sqlite3_result_null(pContext);
191 1 : return;
192 : }
193 : const char *pszDSName =
194 15 : reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
195 :
196 : OGRSQLiteExtensionData *poModule =
197 15 : static_cast<OGRSQLiteExtensionData *>(sqlite3_user_data(pContext));
198 15 : auto poDS = poModule->GetDataset(pszDSName);
199 15 : if (!poDS)
200 : {
201 0 : sqlite3_result_null(pContext);
202 0 : return;
203 : }
204 :
205 15 : OGRSQLite_gdal_get_pixel_value_common("gdal_get_layer_pixel_value",
206 : pContext, argc, argv, poDS);
207 : }
208 :
209 : /************************************************************************/
210 : /* OGRSQLITE_LIKE() */
211 : /************************************************************************/
212 :
213 229782 : static void OGRSQLITE_LIKE(sqlite3_context *pContext, int argc,
214 : sqlite3_value **argv)
215 : {
216 : OGRSQLiteExtensionData *poModule =
217 229782 : static_cast<OGRSQLiteExtensionData *>(sqlite3_user_data(pContext));
218 :
219 : // A LIKE B is implemented as like(B, A)
220 : // A LIKE B ESCAPE C is implemented as like(B, A, C)
221 : const char *pattern =
222 229782 : reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
223 : const char *input =
224 229782 : reinterpret_cast<const char *>(sqlite3_value_text(argv[1]));
225 229782 : if (!input || !pattern)
226 : {
227 8207 : sqlite3_result_null(pContext);
228 8207 : return;
229 : }
230 221575 : char chEscape = '\\';
231 221575 : if (argc == 3)
232 : {
233 : const char *escape =
234 12 : reinterpret_cast<const char *>(sqlite3_value_text(argv[2]));
235 12 : if (!escape || escape[1] != 0)
236 : {
237 6 : sqlite3_result_null(pContext);
238 6 : return;
239 : }
240 6 : chEscape = escape[0];
241 : }
242 :
243 221569 : const bool insensitive = !poModule->GetCaseSensitiveLike();
244 221569 : constexpr bool bUTF8Strings = true;
245 221569 : sqlite3_result_int(pContext, swq_test_like(input, pattern, chEscape,
246 : insensitive, bUTF8Strings));
247 : }
248 :
249 : /************************************************************************/
250 : /* OGRSQLITE_STDDEV_Step() */
251 : /************************************************************************/
252 :
253 : // Welford's online algorithm for variance:
254 : // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm
255 : struct OGRSQLITE_STDDEV_Context
256 : {
257 : int64_t nValues;
258 : double dfMean;
259 : double dfM2; // Accumulator for squared distance from the mean
260 : };
261 :
262 8 : static void OGRSQLITE_STDDEV_Step(sqlite3_context *pContext, int /* argc*/,
263 : sqlite3_value **argv)
264 : {
265 : auto pAggCtxt =
266 8 : static_cast<OGRSQLITE_STDDEV_Context *>(sqlite3_aggregate_context(
267 : pContext, static_cast<int>(sizeof(OGRSQLITE_STDDEV_Context))));
268 8 : const auto eType = sqlite3_value_type(argv[0]);
269 8 : if (eType != SQLITE_INTEGER && eType != SQLITE_FLOAT)
270 4 : return;
271 :
272 4 : const double dfValue = sqlite3_value_double(argv[0]);
273 4 : pAggCtxt->nValues++;
274 4 : const double dfDelta = dfValue - pAggCtxt->dfMean;
275 4 : pAggCtxt->dfMean += dfDelta / pAggCtxt->nValues;
276 4 : const double dfDelta2 = dfValue - pAggCtxt->dfMean;
277 4 : pAggCtxt->dfM2 += dfDelta * dfDelta2;
278 : }
279 :
280 : /************************************************************************/
281 : /* OGRSQLITE_STDDEV_POP_Finalize() */
282 : /************************************************************************/
283 :
284 1 : static void OGRSQLITE_STDDEV_POP_Finalize(sqlite3_context *pContext)
285 : {
286 : auto pAggCtxt =
287 1 : static_cast<OGRSQLITE_STDDEV_Context *>(sqlite3_aggregate_context(
288 : pContext, static_cast<int>(sizeof(OGRSQLITE_STDDEV_Context))));
289 1 : if (pAggCtxt->nValues > 0)
290 : {
291 1 : sqlite3_result_double(pContext,
292 1 : sqrt(pAggCtxt->dfM2 / pAggCtxt->nValues));
293 : }
294 1 : }
295 :
296 : /************************************************************************/
297 : /* OGRSQLITE_STDDEV_SAMP_Finalize() */
298 : /************************************************************************/
299 :
300 1 : static void OGRSQLITE_STDDEV_SAMP_Finalize(sqlite3_context *pContext)
301 : {
302 : auto pAggCtxt =
303 1 : static_cast<OGRSQLITE_STDDEV_Context *>(sqlite3_aggregate_context(
304 : pContext, static_cast<int>(sizeof(OGRSQLITE_STDDEV_Context))));
305 1 : if (pAggCtxt->nValues > 1)
306 : {
307 1 : sqlite3_result_double(pContext,
308 1 : sqrt(pAggCtxt->dfM2 / (pAggCtxt->nValues - 1)));
309 : }
310 1 : }
311 :
312 : /************************************************************************/
313 : /* OGRSQLITE_Percentile_Step() */
314 : /************************************************************************/
315 :
316 : // Percentile related code inspired from https://sqlite.org/src/file/ext/misc/percentile.c
317 : // of https://www.sqlite.org/draft/percentile.html
318 :
319 : // Constant added to Percentile::rPct, since rPct is initialized to 0 when unset.
320 : constexpr double PERCENT_ADD_CONSTANT = 1;
321 :
322 : namespace
323 : {
324 : struct Percentile
325 : {
326 : double rPct; /* PERCENT_ADD_CONSTANT more than the value for P */
327 : std::vector<double> *values; /* Array of Y values */
328 : };
329 : } // namespace
330 :
331 : /*
332 : ** The "step" function for percentile(Y,P) is called once for each
333 : ** input row.
334 : */
335 31 : static void OGRSQLITE_Percentile_Step(sqlite3_context *pCtx, int argc,
336 : sqlite3_value **argv)
337 : {
338 31 : assert(argc == 2 || argc == 1);
339 :
340 : double rPct;
341 :
342 31 : if (argc == 1)
343 : {
344 : /* Requirement 13: median(Y) is the same as percentile(Y,50). */
345 9 : rPct = 50.0;
346 : }
347 22 : else if (sqlite3_user_data(pCtx) == nullptr)
348 : {
349 : /* Requirement 3: P must be a number between 0 and 100 */
350 12 : const int eType = sqlite3_value_numeric_type(argv[1]);
351 12 : rPct = sqlite3_value_double(argv[1]);
352 12 : if ((eType != SQLITE_INTEGER && eType != SQLITE_FLOAT) || rPct < 0.0 ||
353 : rPct > 100.0)
354 : {
355 3 : sqlite3_result_error(pCtx,
356 : "2nd argument to percentile() is not "
357 : "a number between 0.0 and 100.0",
358 : -1);
359 11 : return;
360 : }
361 : }
362 : else
363 : {
364 : /* Requirement 3: P must be a number between 0 and 1 */
365 10 : const int eType = sqlite3_value_numeric_type(argv[1]);
366 10 : rPct = sqlite3_value_double(argv[1]);
367 10 : if ((eType != SQLITE_INTEGER && eType != SQLITE_FLOAT) || rPct < 0.0 ||
368 : rPct > 1.0)
369 : {
370 3 : sqlite3_result_error(pCtx,
371 : "2nd argument to percentile_cont() is not "
372 : "a number between 0.0 and 1.0",
373 : -1);
374 3 : return;
375 : }
376 7 : rPct *= 100.0;
377 : }
378 :
379 : /* Allocate the session context. */
380 : auto p = static_cast<Percentile *>(
381 25 : sqlite3_aggregate_context(pCtx, sizeof(Percentile)));
382 25 : if (!p)
383 0 : return;
384 :
385 : /* Remember the P value. Throw an error if the P value is different
386 : ** from any prior row, per Requirement (2). */
387 25 : if (p->rPct == 0.0)
388 : {
389 11 : p->rPct = rPct + PERCENT_ADD_CONSTANT;
390 : }
391 14 : else if (p->rPct != rPct + PERCENT_ADD_CONSTANT)
392 : {
393 1 : sqlite3_result_error(pCtx,
394 : "2nd argument to percentile() is not the "
395 : "same for all input rows",
396 : -1);
397 1 : return;
398 : }
399 :
400 : /* Ignore rows for which the value is NULL */
401 24 : const int eType = sqlite3_value_type(argv[0]);
402 24 : if (eType == SQLITE_NULL)
403 3 : return;
404 :
405 : /* If not NULL, then Y must be numeric. Otherwise throw an error.
406 : ** Requirement 4 */
407 21 : if (eType != SQLITE_INTEGER && eType != SQLITE_FLOAT)
408 : {
409 1 : sqlite3_result_error(pCtx,
410 : "1st argument to percentile() is not "
411 : "numeric",
412 : -1);
413 1 : return;
414 : }
415 :
416 : /* Ignore rows for which the value is NaN */
417 20 : const double v = sqlite3_value_double(argv[0]);
418 20 : if (std::isnan(v))
419 : {
420 0 : return;
421 : }
422 :
423 20 : if (!p->values)
424 11 : p->values = new std::vector<double>();
425 : try
426 : {
427 20 : p->values->push_back(v);
428 : }
429 0 : catch (const std::exception &)
430 : {
431 0 : delete p->values;
432 0 : memset(p, 0, sizeof(*p));
433 0 : sqlite3_result_error_nomem(pCtx);
434 0 : return;
435 : }
436 : }
437 :
438 : /************************************************************************/
439 : /* OGRSQLITE_Percentile_Finalize() */
440 : /************************************************************************/
441 :
442 : /*
443 : ** Called to compute the final output of percentile() and to clean
444 : ** up all allocated memory.
445 : */
446 14 : static void OGRSQLITE_Percentile_Finalize(sqlite3_context *pCtx)
447 : {
448 14 : auto p = static_cast<Percentile *>(sqlite3_aggregate_context(pCtx, 0));
449 14 : if (!p)
450 3 : return;
451 11 : if (!p->values)
452 0 : return;
453 11 : if (!p->values->empty())
454 : {
455 11 : std::sort(p->values->begin(), p->values->end());
456 22 : const double ix = (p->rPct - PERCENT_ADD_CONSTANT) *
457 11 : static_cast<double>(p->values->size() - 1) * 0.01;
458 11 : const size_t i1 = static_cast<size_t>(ix);
459 : const size_t i2 =
460 3 : ix == static_cast<double>(i1) || i1 == p->values->size() - 1
461 14 : ? i1
462 11 : : i1 + 1;
463 11 : const double v1 = (*p->values)[i1];
464 11 : const double v2 = (*p->values)[i2];
465 11 : const double vx = v1 + (v2 - v1) * static_cast<double>(ix - i1);
466 11 : sqlite3_result_double(pCtx, vx);
467 : }
468 11 : delete p->values;
469 11 : memset(p, 0, sizeof(*p));
470 : }
471 :
472 : /************************************************************************/
473 : /* OGRSQLITE_Mode_Step() */
474 : /************************************************************************/
475 :
476 : namespace
477 : {
478 : struct Mode
479 : {
480 : std::map<double, uint64_t> *numericValues;
481 : std::map<std::string, uint64_t> *stringValues;
482 : double mostFrequentNumValue;
483 : std::string *mostFrequentStr;
484 : uint64_t mostFrequentValueCount;
485 : bool mostFrequentValueIsStr;
486 : };
487 : } // namespace
488 :
489 19 : static void OGRSQLITE_Mode_Step(sqlite3_context *pCtx, int /*argc*/,
490 : sqlite3_value **argv)
491 : {
492 19 : const int eType = sqlite3_value_type(argv[0]);
493 19 : if (eType == SQLITE_NULL)
494 1 : return;
495 :
496 18 : if (eType == SQLITE_BLOB)
497 : {
498 0 : sqlite3_result_error(pCtx, "BLOB argument not supported for mode()",
499 : -1);
500 0 : return;
501 : }
502 :
503 : /* Allocate the session context. */
504 18 : auto p = static_cast<Mode *>(sqlite3_aggregate_context(pCtx, sizeof(Mode)));
505 18 : if (!p)
506 0 : return;
507 :
508 : try
509 : {
510 18 : if (eType == SQLITE_TEXT)
511 : {
512 : const char *pszStr =
513 9 : reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
514 9 : if (!p->stringValues)
515 : {
516 3 : p->stringValues = new std::map<std::string, uint64_t>();
517 3 : p->mostFrequentStr = new std::string();
518 : }
519 9 : const uint64_t count = ++(*p->stringValues)[pszStr];
520 9 : if (count > p->mostFrequentValueCount)
521 : {
522 4 : p->mostFrequentValueCount = count;
523 4 : p->mostFrequentValueIsStr = true;
524 4 : *(p->mostFrequentStr) = pszStr;
525 : }
526 : }
527 : else
528 : {
529 9 : const double v = sqlite3_value_double(argv[0]);
530 9 : if (std::isnan(v))
531 0 : return;
532 9 : if (!p->numericValues)
533 3 : p->numericValues = new std::map<double, uint64_t>();
534 9 : const uint64_t count = ++(*p->numericValues)[v];
535 9 : if (count > p->mostFrequentValueCount)
536 : {
537 4 : p->mostFrequentValueCount = count;
538 4 : p->mostFrequentValueIsStr = false;
539 4 : p->mostFrequentNumValue = v;
540 : }
541 : }
542 : }
543 0 : catch (const std::exception &)
544 : {
545 0 : delete p->stringValues;
546 0 : delete p->numericValues;
547 0 : delete p->mostFrequentStr;
548 0 : memset(p, 0, sizeof(*p));
549 0 : sqlite3_result_error_nomem(pCtx);
550 0 : return;
551 : }
552 : }
553 :
554 : /************************************************************************/
555 : /* OGRSQLITE_Mode_Finalize() */
556 : /************************************************************************/
557 :
558 5 : static void OGRSQLITE_Mode_Finalize(sqlite3_context *pCtx)
559 : {
560 5 : auto p = static_cast<Mode *>(sqlite3_aggregate_context(pCtx, 0));
561 5 : if (!p)
562 1 : return;
563 :
564 4 : if (p->mostFrequentValueCount)
565 : {
566 4 : if (p->mostFrequentValueIsStr)
567 : {
568 3 : sqlite3_result_text(pCtx, p->mostFrequentStr->c_str(), -1,
569 : SQLITE_TRANSIENT);
570 : }
571 : else
572 : {
573 1 : sqlite3_result_double(pCtx, p->mostFrequentNumValue);
574 : }
575 : }
576 :
577 4 : delete p->stringValues;
578 4 : delete p->numericValues;
579 4 : delete p->mostFrequentStr;
580 4 : memset(p, 0, sizeof(*p));
581 : }
582 :
583 : /************************************************************************/
584 : /* OGRSQLITE_ST_Hilbert_X_Y_BBOX() */
585 : /************************************************************************/
586 :
587 14 : static void OGRSQLITE_ST_Hilbert_X_Y_BBOX(sqlite3_context *pContext,
588 : [[maybe_unused]] int argc,
589 : sqlite3_value **argv)
590 : {
591 14 : CPLAssert(argc == 6);
592 14 : const double dfX = sqlite3_value_double(argv[0]);
593 14 : const double dfY = sqlite3_value_double(argv[1]);
594 14 : OGREnvelope sExtent;
595 14 : sExtent.MinX = sqlite3_value_double(argv[2]);
596 14 : sExtent.MinY = sqlite3_value_double(argv[3]);
597 14 : sExtent.MaxX = sqlite3_value_double(argv[4]);
598 14 : sExtent.MaxY = sqlite3_value_double(argv[5]);
599 14 : if (!(dfX >= sExtent.MinX && dfY >= sExtent.MinY && dfX <= sExtent.MaxX &&
600 8 : dfY <= sExtent.MaxY))
601 : {
602 8 : CPLError(CE_Warning, CPLE_AppDefined,
603 : "ST_Hilbert(): (%g, %g) is not within passed bounding box",
604 : dfX, dfY);
605 8 : sqlite3_result_null(pContext);
606 8 : return;
607 : }
608 6 : sqlite3_result_int64(pContext, GDALHilbertCode(&sExtent, dfX, dfY));
609 : }
610 :
611 : /************************************************************************/
612 : /* OGRSQLiteRegisterSQLFunctionsCommon() */
613 : /************************************************************************/
614 :
615 : #ifndef SQLITE_DETERMINISTIC
616 : #define SQLITE_DETERMINISTIC 0
617 : #endif
618 :
619 : #ifndef SQLITE_INNOCUOUS
620 : #define SQLITE_INNOCUOUS 0
621 : #endif
622 :
623 : #define UTF8_INNOCUOUS (SQLITE_UTF8 | SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS)
624 :
625 3601 : static OGRSQLiteExtensionData *OGRSQLiteRegisterSQLFunctionsCommon(sqlite3 *hDB)
626 : {
627 3601 : OGRSQLiteExtensionData *pData = new OGRSQLiteExtensionData(hDB);
628 :
629 3601 : sqlite3_create_function(hDB, "gdal_get_pixel_value", 5, SQLITE_UTF8, pData,
630 : OGRSQLITE_gdal_get_pixel_value, nullptr, nullptr);
631 3601 : sqlite3_create_function(hDB, "gdal_get_pixel_value", 6, SQLITE_UTF8, pData,
632 : OGRSQLITE_gdal_get_pixel_value, nullptr, nullptr);
633 :
634 3601 : if (CPLTestBool(CPLGetConfigOption("OGR_SQLITE_USE_CUSTOM_LIKE", "YES")))
635 : {
636 3601 : sqlite3_create_function(hDB, "LIKE", 2, UTF8_INNOCUOUS, pData,
637 : OGRSQLITE_LIKE, nullptr, nullptr);
638 3601 : sqlite3_create_function(hDB, "LIKE", 3, UTF8_INNOCUOUS, pData,
639 : OGRSQLITE_LIKE, nullptr, nullptr);
640 : }
641 :
642 3601 : sqlite3_create_function(hDB, "STDDEV_POP", 1, UTF8_INNOCUOUS, nullptr,
643 : nullptr, OGRSQLITE_STDDEV_Step,
644 : OGRSQLITE_STDDEV_POP_Finalize);
645 :
646 3601 : sqlite3_create_function(hDB, "STDDEV_SAMP", 1, UTF8_INNOCUOUS, nullptr,
647 : nullptr, OGRSQLITE_STDDEV_Step,
648 : OGRSQLITE_STDDEV_SAMP_Finalize);
649 :
650 3601 : sqlite3_create_function(hDB, "median", 1, UTF8_INNOCUOUS, nullptr, nullptr,
651 : OGRSQLITE_Percentile_Step,
652 : OGRSQLITE_Percentile_Finalize);
653 :
654 3601 : sqlite3_create_function(hDB, "percentile", 2, UTF8_INNOCUOUS, nullptr,
655 : nullptr, OGRSQLITE_Percentile_Step,
656 : OGRSQLITE_Percentile_Finalize);
657 :
658 3601 : sqlite3_create_function(
659 : hDB, "percentile_cont", 2, UTF8_INNOCUOUS,
660 : const_cast<char *>("percentile_cont"), // any non-null ptr
661 : nullptr, OGRSQLITE_Percentile_Step, OGRSQLITE_Percentile_Finalize);
662 :
663 3601 : sqlite3_create_function(hDB, "mode", 1, UTF8_INNOCUOUS, nullptr, nullptr,
664 : OGRSQLITE_Mode_Step, OGRSQLITE_Mode_Finalize);
665 :
666 : // ST_Hilbert() inspired from https://duckdb.org/docs/stable/core_extensions/spatial/functions#st_hilbert
667 :
668 : // X,Y,minX,minY,maxX,maxY
669 3601 : sqlite3_create_function(hDB, "ST_Hilbert", 2 + 4, UTF8_INNOCUOUS, nullptr,
670 : OGRSQLITE_ST_Hilbert_X_Y_BBOX, nullptr, nullptr);
671 :
672 3601 : pData->SetRegExpCache(OGRSQLiteRegisterRegExpFunction(hDB));
673 :
674 3601 : return pData;
675 : }
676 :
677 : /************************************************************************/
678 : /* OGRSQLiteUnregisterSQLFunctions() */
679 : /************************************************************************/
680 :
681 3964 : static void OGRSQLiteUnregisterSQLFunctions(void *hHandle)
682 : {
683 3964 : OGRSQLiteExtensionData *pData =
684 : static_cast<OGRSQLiteExtensionData *>(hHandle);
685 3964 : delete pData;
686 3964 : }
687 :
688 : #ifdef DEFINE_OGRSQLiteSQLFunctionsSetCaseSensitiveLike
689 : /************************************************************************/
690 : /* OGRSQLiteSQLFunctionsSetCaseSensitiveLike() */
691 : /************************************************************************/
692 :
693 4 : static void OGRSQLiteSQLFunctionsSetCaseSensitiveLike(void *hHandle, bool b)
694 : {
695 4 : OGRSQLiteExtensionData *pData =
696 : static_cast<OGRSQLiteExtensionData *>(hHandle);
697 4 : pData->SetCaseSensitiveLike(b);
698 4 : }
699 : #endif
|