1 /* 2 ** 2018-05-25 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** This file implements an alternative R-Tree virtual table that 14 ** uses polygons to express the boundaries of 2-dimensional objects. 15 ** 16 ** This file is #include-ed onto the end of "rtree.c" so that it has 17 ** access to all of the R-Tree internals. 18 */ 19 #include <stdlib.h> 20 21 /* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */ 22 #ifdef GEOPOLY_ENABLE_DEBUG 23 static int geo_debug = 0; 24 # define GEODEBUG(X) if(geo_debug)printf X 25 #else 26 # define GEODEBUG(X) 27 #endif 28 29 /* Character class routines */ 30 #ifdef sqlite3Isdigit 31 /* Use the SQLite core versions if this routine is part of the 32 ** SQLite amalgamation */ 33 # define safe_isdigit(x) sqlite3Isdigit(x) 34 # define safe_isalnum(x) sqlite3Isalnum(x) 35 # define safe_isxdigit(x) sqlite3Isxdigit(x) 36 #else 37 /* Use the standard library for separate compilation */ 38 #include <ctype.h> /* amalgamator: keep */ 39 # define safe_isdigit(x) isdigit((unsigned char)(x)) 40 # define safe_isalnum(x) isalnum((unsigned char)(x)) 41 # define safe_isxdigit(x) isxdigit((unsigned char)(x)) 42 #endif 43 44 #ifndef JSON_NULL /* The following stuff repeats things found in json1 */ 45 /* 46 ** Growing our own isspace() routine this way is twice as fast as 47 ** the library isspace() function. 48 */ 49 static const char geopolyIsSpace[] = { 50 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66 }; 67 #define fast_isspace(x) (geopolyIsSpace[(unsigned char)x]) 68 #endif /* JSON NULL - back to original code */ 69 70 /* Compiler and version */ 71 #ifndef GCC_VERSION 72 #if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) 73 # define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) 74 #else 75 # define GCC_VERSION 0 76 #endif 77 #endif 78 #ifndef MSVC_VERSION 79 #if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) 80 # define MSVC_VERSION _MSC_VER 81 #else 82 # define MSVC_VERSION 0 83 #endif 84 #endif 85 86 /* Datatype for coordinates 87 */ 88 typedef float GeoCoord; 89 90 /* 91 ** Internal representation of a polygon. 92 ** 93 ** The polygon consists of a sequence of vertexes. There is a line 94 ** segment between each pair of vertexes, and one final segment from 95 ** the last vertex back to the first. (This differs from the GeoJSON 96 ** standard in which the final vertex is a repeat of the first.) 97 ** 98 ** The polygon follows the right-hand rule. The area to the right of 99 ** each segment is "outside" and the area to the left is "inside". 100 ** 101 ** The on-disk representation consists of a 4-byte header followed by 102 ** the values. The 4-byte header is: 103 ** 104 ** encoding (1 byte) 0=big-endian, 1=little-endian 105 ** nvertex (3 bytes) Number of vertexes as a big-endian integer 106 ** 107 ** Enough space is allocated for 4 coordinates, to work around over-zealous 108 ** warnings coming from some compiler (notably, clang). In reality, the size 109 ** of each GeoPoly memory allocate is adjusted as necessary so that the 110 ** GeoPoly.a[] array at the end is the appropriate size. 111 */ 112 typedef struct GeoPoly GeoPoly; 113 struct GeoPoly { 114 int nVertex; /* Number of vertexes */ 115 unsigned char hdr[4]; /* Header for on-disk representation */ 116 GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ 117 }; 118 119 /* The size of a memory allocation needed for a GeoPoly object sufficient 120 ** to hold N coordinate pairs. 121 */ 122 #define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) 123 124 /* Macros to access coordinates of a GeoPoly. 125 ** We have to use these macros, rather than just say p->a[i] in order 126 ** to silence (incorrect) UBSAN warnings if the array index is too large. 127 */ 128 #define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2]) 129 #define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1]) 130 131 132 /* 133 ** State of a parse of a GeoJSON input. 134 */ 135 typedef struct GeoParse GeoParse; 136 struct GeoParse { 137 const unsigned char *z; /* Unparsed input */ 138 int nVertex; /* Number of vertexes in a[] */ 139 int nAlloc; /* Space allocated to a[] */ 140 int nErr; /* Number of errors encountered */ 141 GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ 142 }; 143 144 /* Do a 4-byte byte swap */ 145 static void geopolySwab32(unsigned char *a){ 146 unsigned char t = a[0]; 147 a[0] = a[3]; 148 a[3] = t; 149 t = a[1]; 150 a[1] = a[2]; 151 a[2] = t; 152 } 153 154 /* Skip whitespace. Return the next non-whitespace character. */ 155 static char geopolySkipSpace(GeoParse *p){ 156 while( fast_isspace(p->z[0]) ) p->z++; 157 return p->z[0]; 158 } 159 160 /* Parse out a number. Write the value into *pVal if pVal!=0. 161 ** return non-zero on success and zero if the next token is not a number. 162 */ 163 static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ 164 char c = geopolySkipSpace(p); 165 const unsigned char *z = p->z; 166 int j = 0; 167 int seenDP = 0; 168 int seenE = 0; 169 if( c=='-' ){ 170 j = 1; 171 c = z[j]; 172 } 173 if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; 174 for(;; j++){ 175 c = z[j]; 176 if( safe_isdigit(c) ) continue; 177 if( c=='.' ){ 178 if( z[j-1]=='-' ) return 0; 179 if( seenDP ) return 0; 180 seenDP = 1; 181 continue; 182 } 183 if( c=='e' || c=='E' ){ 184 if( z[j-1]<'0' ) return 0; 185 if( seenE ) return -1; 186 seenDP = seenE = 1; 187 c = z[j+1]; 188 if( c=='+' || c=='-' ){ 189 j++; 190 c = z[j+1]; 191 } 192 if( c<'0' || c>'9' ) return 0; 193 continue; 194 } 195 break; 196 } 197 if( z[j-1]<'0' ) return 0; 198 if( pVal ){ 199 #ifdef SQLITE_AMALGAMATION 200 /* The sqlite3AtoF() routine is much much faster than atof(), if it 201 ** is available */ 202 double r; 203 (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); 204 *pVal = r; 205 #else 206 *pVal = (GeoCoord)atof((const char*)p->z); 207 #endif 208 } 209 p->z += j; 210 return 1; 211 } 212 213 /* 214 ** If the input is a well-formed JSON array of coordinates with at least 215 ** four coordinates and where each coordinate is itself a two-value array, 216 ** then convert the JSON into a GeoPoly object and return a pointer to 217 ** that object. 218 ** 219 ** If any error occurs, return NULL. 220 */ 221 static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ 222 GeoParse s; 223 int rc = SQLITE_OK; 224 memset(&s, 0, sizeof(s)); 225 s.z = z; 226 if( geopolySkipSpace(&s)=='[' ){ 227 s.z++; 228 while( geopolySkipSpace(&s)=='[' ){ 229 int ii = 0; 230 char c; 231 s.z++; 232 if( s.nVertex>=s.nAlloc ){ 233 GeoCoord *aNew; 234 s.nAlloc = s.nAlloc*2 + 16; 235 aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); 236 if( aNew==0 ){ 237 rc = SQLITE_NOMEM; 238 s.nErr++; 239 break; 240 } 241 s.a = aNew; 242 } 243 while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ 244 ii++; 245 if( ii==2 ) s.nVertex++; 246 c = geopolySkipSpace(&s); 247 s.z++; 248 if( c==',' ) continue; 249 if( c==']' && ii>=2 ) break; 250 s.nErr++; 251 rc = SQLITE_ERROR; 252 goto parse_json_err; 253 } 254 if( geopolySkipSpace(&s)==',' ){ 255 s.z++; 256 continue; 257 } 258 break; 259 } 260 if( geopolySkipSpace(&s)==']' 261 && s.nVertex>=4 262 && s.a[0]==s.a[s.nVertex*2-2] 263 && s.a[1]==s.a[s.nVertex*2-1] 264 && (s.z++, geopolySkipSpace(&s)==0) 265 ){ 266 GeoPoly *pOut; 267 int x = 1; 268 s.nVertex--; /* Remove the redundant vertex at the end */ 269 pOut = sqlite3_malloc64( GEOPOLY_SZ((sqlite3_int64)s.nVertex) ); 270 x = 1; 271 if( pOut==0 ) goto parse_json_err; 272 pOut->nVertex = s.nVertex; 273 memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); 274 pOut->hdr[0] = *(unsigned char*)&x; 275 pOut->hdr[1] = (s.nVertex>>16)&0xff; 276 pOut->hdr[2] = (s.nVertex>>8)&0xff; 277 pOut->hdr[3] = s.nVertex&0xff; 278 sqlite3_free(s.a); 279 if( pRc ) *pRc = SQLITE_OK; 280 return pOut; 281 }else{ 282 s.nErr++; 283 rc = SQLITE_ERROR; 284 } 285 } 286 parse_json_err: 287 if( pRc ) *pRc = rc; 288 sqlite3_free(s.a); 289 return 0; 290 } 291 292 /* 293 ** Given a function parameter, try to interpret it as a polygon, either 294 ** in the binary format or JSON text. Compute a GeoPoly object and 295 ** return a pointer to that object. Or if the input is not a well-formed 296 ** polygon, put an error message in sqlite3_context and return NULL. 297 */ 298 static GeoPoly *geopolyFuncParam( 299 sqlite3_context *pCtx, /* Context for error messages */ 300 sqlite3_value *pVal, /* The value to decode */ 301 int *pRc /* Write error here */ 302 ){ 303 GeoPoly *p = 0; 304 int nByte; 305 testcase( pCtx==0 ); 306 if( sqlite3_value_type(pVal)==SQLITE_BLOB 307 && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord)) 308 ){ 309 const unsigned char *a = sqlite3_value_blob(pVal); 310 int nVertex; 311 if( a==0 ){ 312 if( pCtx ) sqlite3_result_error_nomem(pCtx); 313 return 0; 314 } 315 nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; 316 if( (a[0]==0 || a[0]==1) 317 && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte 318 ){ 319 p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); 320 if( p==0 ){ 321 if( pRc ) *pRc = SQLITE_NOMEM; 322 if( pCtx ) sqlite3_result_error_nomem(pCtx); 323 }else{ 324 int x = 1; 325 p->nVertex = nVertex; 326 memcpy(p->hdr, a, nByte); 327 if( a[0] != *(unsigned char*)&x ){ 328 int ii; 329 for(ii=0; ii<nVertex; ii++){ 330 geopolySwab32((unsigned char*)&GeoX(p,ii)); 331 geopolySwab32((unsigned char*)&GeoY(p,ii)); 332 } 333 p->hdr[0] ^= 1; 334 } 335 } 336 } 337 if( pRc ) *pRc = SQLITE_OK; 338 return p; 339 }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ 340 const unsigned char *zJson = sqlite3_value_text(pVal); 341 if( zJson==0 ){ 342 if( pRc ) *pRc = SQLITE_NOMEM; 343 return 0; 344 } 345 return geopolyParseJson(zJson, pRc); 346 }else{ 347 if( pRc ) *pRc = SQLITE_ERROR; 348 return 0; 349 } 350 } 351 352 /* 353 ** Implementation of the geopoly_blob(X) function. 354 ** 355 ** If the input is a well-formed Geopoly BLOB or JSON string 356 ** then return the BLOB representation of the polygon. Otherwise 357 ** return NULL. 358 */ 359 static void geopolyBlobFunc( 360 sqlite3_context *context, 361 int argc, 362 sqlite3_value **argv 363 ){ 364 GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 365 if( p ){ 366 sqlite3_result_blob(context, p->hdr, 367 4+8*p->nVertex, SQLITE_TRANSIENT); 368 sqlite3_free(p); 369 } 370 } 371 372 /* 373 ** SQL function: geopoly_json(X) 374 ** 375 ** Interpret X as a polygon and render it as a JSON array 376 ** of coordinates. Or, if X is not a valid polygon, return NULL. 377 */ 378 static void geopolyJsonFunc( 379 sqlite3_context *context, 380 int argc, 381 sqlite3_value **argv 382 ){ 383 GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 384 if( p ){ 385 sqlite3 *db = sqlite3_context_db_handle(context); 386 sqlite3_str *x = sqlite3_str_new(db); 387 int i; 388 sqlite3_str_append(x, "[", 1); 389 for(i=0; i<p->nVertex; i++){ 390 sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i)); 391 } 392 sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0)); 393 sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); 394 sqlite3_free(p); 395 } 396 } 397 398 /* 399 ** SQL function: geopoly_svg(X, ....) 400 ** 401 ** Interpret X as a polygon and render it as a SVG <polyline>. 402 ** Additional arguments are added as attributes to the <polyline>. 403 */ 404 static void geopolySvgFunc( 405 sqlite3_context *context, 406 int argc, 407 sqlite3_value **argv 408 ){ 409 GeoPoly *p; 410 if( argc<1 ) return; 411 p = geopolyFuncParam(context, argv[0], 0); 412 if( p ){ 413 sqlite3 *db = sqlite3_context_db_handle(context); 414 sqlite3_str *x = sqlite3_str_new(db); 415 int i; 416 char cSep = '\''; 417 sqlite3_str_appendf(x, "<polyline points="); 418 for(i=0; i<p->nVertex; i++){ 419 sqlite3_str_appendf(x, "%c%g,%g", cSep, GeoX(p,i), GeoY(p,i)); 420 cSep = ' '; 421 } 422 sqlite3_str_appendf(x, " %g,%g'", GeoX(p,0), GeoY(p,0)); 423 for(i=1; i<argc; i++){ 424 const char *z = (const char*)sqlite3_value_text(argv[i]); 425 if( z && z[0] ){ 426 sqlite3_str_appendf(x, " %s", z); 427 } 428 } 429 sqlite3_str_appendf(x, "></polyline>"); 430 sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); 431 sqlite3_free(p); 432 } 433 } 434 435 /* 436 ** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) 437 ** 438 ** Transform and/or translate a polygon as follows: 439 ** 440 ** x1 = A*x0 + B*y0 + E 441 ** y1 = C*x0 + D*y0 + F 442 ** 443 ** For a translation: 444 ** 445 ** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) 446 ** 447 ** Rotate by R around the point (0,0): 448 ** 449 ** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) 450 */ 451 static void geopolyXformFunc( 452 sqlite3_context *context, 453 int argc, 454 sqlite3_value **argv 455 ){ 456 GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 457 double A = sqlite3_value_double(argv[1]); 458 double B = sqlite3_value_double(argv[2]); 459 double C = sqlite3_value_double(argv[3]); 460 double D = sqlite3_value_double(argv[4]); 461 double E = sqlite3_value_double(argv[5]); 462 double F = sqlite3_value_double(argv[6]); 463 GeoCoord x1, y1, x0, y0; 464 int ii; 465 if( p ){ 466 for(ii=0; ii<p->nVertex; ii++){ 467 x0 = GeoX(p,ii); 468 y0 = GeoY(p,ii); 469 x1 = (GeoCoord)(A*x0 + B*y0 + E); 470 y1 = (GeoCoord)(C*x0 + D*y0 + F); 471 GeoX(p,ii) = x1; 472 GeoY(p,ii) = y1; 473 } 474 sqlite3_result_blob(context, p->hdr, 475 4+8*p->nVertex, SQLITE_TRANSIENT); 476 sqlite3_free(p); 477 } 478 } 479 480 /* 481 ** Compute the area enclosed by the polygon. 482 ** 483 ** This routine can also be used to detect polygons that rotate in 484 ** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). 485 ** This routine returns a negative value for clockwise (CW) polygons. 486 */ 487 static double geopolyArea(GeoPoly *p){ 488 double rArea = 0.0; 489 int ii; 490 for(ii=0; ii<p->nVertex-1; ii++){ 491 rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */ 492 * (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */ 493 * 0.5; 494 } 495 rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */ 496 * (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */ 497 * 0.5; 498 return rArea; 499 } 500 501 /* 502 ** Implementation of the geopoly_area(X) function. 503 ** 504 ** If the input is a well-formed Geopoly BLOB then return the area 505 ** enclosed by the polygon. If the polygon circulates clockwise instead 506 ** of counterclockwise (as it should) then return the negative of the 507 ** enclosed area. Otherwise return NULL. 508 */ 509 static void geopolyAreaFunc( 510 sqlite3_context *context, 511 int argc, 512 sqlite3_value **argv 513 ){ 514 GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 515 if( p ){ 516 sqlite3_result_double(context, geopolyArea(p)); 517 sqlite3_free(p); 518 } 519 } 520 521 /* 522 ** Implementation of the geopoly_ccw(X) function. 523 ** 524 ** If the rotation of polygon X is clockwise (incorrect) instead of 525 ** counter-clockwise (the correct winding order according to RFC7946) 526 ** then reverse the order of the vertexes in polygon X. 527 ** 528 ** In other words, this routine returns a CCW polygon regardless of the 529 ** winding order of its input. 530 ** 531 ** Use this routine to sanitize historical inputs that that sometimes 532 ** contain polygons that wind in the wrong direction. 533 */ 534 static void geopolyCcwFunc( 535 sqlite3_context *context, 536 int argc, 537 sqlite3_value **argv 538 ){ 539 GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 540 if( p ){ 541 if( geopolyArea(p)<0.0 ){ 542 int ii, jj; 543 for(ii=1, jj=p->nVertex-1; ii<jj; ii++, jj--){ 544 GeoCoord t = GeoX(p,ii); 545 GeoX(p,ii) = GeoX(p,jj); 546 GeoX(p,jj) = t; 547 t = GeoY(p,ii); 548 GeoY(p,ii) = GeoY(p,jj); 549 GeoY(p,jj) = t; 550 } 551 } 552 sqlite3_result_blob(context, p->hdr, 553 4+8*p->nVertex, SQLITE_TRANSIENT); 554 sqlite3_free(p); 555 } 556 } 557 558 #define GEOPOLY_PI 3.1415926535897932385 559 560 /* Fast approximation for sine(X) for X between -0.5*pi and 2*pi 561 */ 562 static double geopolySine(double r){ 563 assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); 564 if( r>=1.5*GEOPOLY_PI ){ 565 r -= 2.0*GEOPOLY_PI; 566 } 567 if( r>=0.5*GEOPOLY_PI ){ 568 return -geopolySine(r-GEOPOLY_PI); 569 }else{ 570 double r2 = r*r; 571 double r3 = r2*r; 572 double r5 = r3*r2; 573 return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; 574 } 575 } 576 577 /* 578 ** Function: geopoly_regular(X,Y,R,N) 579 ** 580 ** Construct a simple, convex, regular polygon centered at X, Y 581 ** with circumradius R and with N sides. 582 */ 583 static void geopolyRegularFunc( 584 sqlite3_context *context, 585 int argc, 586 sqlite3_value **argv 587 ){ 588 double x = sqlite3_value_double(argv[0]); 589 double y = sqlite3_value_double(argv[1]); 590 double r = sqlite3_value_double(argv[2]); 591 int n = sqlite3_value_int(argv[3]); 592 int i; 593 GeoPoly *p; 594 595 if( n<3 || r<=0.0 ) return; 596 if( n>1000 ) n = 1000; 597 p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); 598 if( p==0 ){ 599 sqlite3_result_error_nomem(context); 600 return; 601 } 602 i = 1; 603 p->hdr[0] = *(unsigned char*)&i; 604 p->hdr[1] = 0; 605 p->hdr[2] = (n>>8)&0xff; 606 p->hdr[3] = n&0xff; 607 for(i=0; i<n; i++){ 608 double rAngle = 2.0*GEOPOLY_PI*i/n; 609 GeoX(p,i) = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); 610 GeoY(p,i) = y + r*geopolySine(rAngle); 611 } 612 sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); 613 sqlite3_free(p); 614 } 615 616 /* 617 ** If pPoly is a polygon, compute its bounding box. Then: 618 ** 619 ** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL 620 ** (2) otherwise, compute a GeoPoly for the bounding box and return the 621 ** new GeoPoly 622 ** 623 ** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from 624 ** the bounding box in aCoord and return a pointer to that GeoPoly. 625 */ 626 static GeoPoly *geopolyBBox( 627 sqlite3_context *context, /* For recording the error */ 628 sqlite3_value *pPoly, /* The polygon */ 629 RtreeCoord *aCoord, /* Results here */ 630 int *pRc /* Error code here */ 631 ){ 632 GeoPoly *pOut = 0; 633 GeoPoly *p; 634 float mnX, mxX, mnY, mxY; 635 if( pPoly==0 && aCoord!=0 ){ 636 p = 0; 637 mnX = aCoord[0].f; 638 mxX = aCoord[1].f; 639 mnY = aCoord[2].f; 640 mxY = aCoord[3].f; 641 goto geopolyBboxFill; 642 }else{ 643 p = geopolyFuncParam(context, pPoly, pRc); 644 } 645 if( p ){ 646 int ii; 647 mnX = mxX = GeoX(p,0); 648 mnY = mxY = GeoY(p,0); 649 for(ii=1; ii<p->nVertex; ii++){ 650 double r = GeoX(p,ii); 651 if( r<mnX ) mnX = (float)r; 652 else if( r>mxX ) mxX = (float)r; 653 r = GeoY(p,ii); 654 if( r<mnY ) mnY = (float)r; 655 else if( r>mxY ) mxY = (float)r; 656 } 657 if( pRc ) *pRc = SQLITE_OK; 658 if( aCoord==0 ){ 659 geopolyBboxFill: 660 pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4)); 661 if( pOut==0 ){ 662 sqlite3_free(p); 663 if( context ) sqlite3_result_error_nomem(context); 664 if( pRc ) *pRc = SQLITE_NOMEM; 665 return 0; 666 } 667 pOut->nVertex = 4; 668 ii = 1; 669 pOut->hdr[0] = *(unsigned char*)ⅈ 670 pOut->hdr[1] = 0; 671 pOut->hdr[2] = 0; 672 pOut->hdr[3] = 4; 673 GeoX(pOut,0) = mnX; 674 GeoY(pOut,0) = mnY; 675 GeoX(pOut,1) = mxX; 676 GeoY(pOut,1) = mnY; 677 GeoX(pOut,2) = mxX; 678 GeoY(pOut,2) = mxY; 679 GeoX(pOut,3) = mnX; 680 GeoY(pOut,3) = mxY; 681 }else{ 682 sqlite3_free(p); 683 aCoord[0].f = mnX; 684 aCoord[1].f = mxX; 685 aCoord[2].f = mnY; 686 aCoord[3].f = mxY; 687 } 688 }else if( aCoord ){ 689 memset(aCoord, 0, sizeof(RtreeCoord)*4); 690 } 691 return pOut; 692 } 693 694 /* 695 ** Implementation of the geopoly_bbox(X) SQL function. 696 */ 697 static void geopolyBBoxFunc( 698 sqlite3_context *context, 699 int argc, 700 sqlite3_value **argv 701 ){ 702 GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); 703 if( p ){ 704 sqlite3_result_blob(context, p->hdr, 705 4+8*p->nVertex, SQLITE_TRANSIENT); 706 sqlite3_free(p); 707 } 708 } 709 710 /* 711 ** State vector for the geopoly_group_bbox() aggregate function. 712 */ 713 typedef struct GeoBBox GeoBBox; 714 struct GeoBBox { 715 int isInit; 716 RtreeCoord a[4]; 717 }; 718 719 720 /* 721 ** Implementation of the geopoly_group_bbox(X) aggregate SQL function. 722 */ 723 static void geopolyBBoxStep( 724 sqlite3_context *context, 725 int argc, 726 sqlite3_value **argv 727 ){ 728 RtreeCoord a[4]; 729 int rc = SQLITE_OK; 730 (void)geopolyBBox(context, argv[0], a, &rc); 731 if( rc==SQLITE_OK ){ 732 GeoBBox *pBBox; 733 pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); 734 if( pBBox==0 ) return; 735 if( pBBox->isInit==0 ){ 736 pBBox->isInit = 1; 737 memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); 738 }else{ 739 if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; 740 if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; 741 if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; 742 if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; 743 } 744 } 745 } 746 static void geopolyBBoxFinal( 747 sqlite3_context *context 748 ){ 749 GeoPoly *p; 750 GeoBBox *pBBox; 751 pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); 752 if( pBBox==0 ) return; 753 p = geopolyBBox(context, 0, pBBox->a, 0); 754 if( p ){ 755 sqlite3_result_blob(context, p->hdr, 756 4+8*p->nVertex, SQLITE_TRANSIENT); 757 sqlite3_free(p); 758 } 759 } 760 761 762 /* 763 ** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). 764 ** Returns: 765 ** 766 ** +2 x0,y0 is on the line segement 767 ** 768 ** +1 x0,y0 is beneath line segment 769 ** 770 ** 0 x0,y0 is not on or beneath the line segment or the line segment 771 ** is vertical and x0,y0 is not on the line segment 772 ** 773 ** The left-most coordinate min(x1,x2) is not considered to be part of 774 ** the line segment for the purposes of this analysis. 775 */ 776 static int pointBeneathLine( 777 double x0, double y0, 778 double x1, double y1, 779 double x2, double y2 780 ){ 781 double y; 782 if( x0==x1 && y0==y1 ) return 2; 783 if( x1<x2 ){ 784 if( x0<=x1 || x0>x2 ) return 0; 785 }else if( x1>x2 ){ 786 if( x0<=x2 || x0>x1 ) return 0; 787 }else{ 788 /* Vertical line segment */ 789 if( x0!=x1 ) return 0; 790 if( y0<y1 && y0<y2 ) return 0; 791 if( y0>y1 && y0>y2 ) return 0; 792 return 2; 793 } 794 y = y1 + (y2-y1)*(x0-x1)/(x2-x1); 795 if( y0==y ) return 2; 796 if( y0<y ) return 1; 797 return 0; 798 } 799 800 /* 801 ** SQL function: geopoly_contains_point(P,X,Y) 802 ** 803 ** Return +2 if point X,Y is within polygon P. 804 ** Return +1 if point X,Y is on the polygon boundary. 805 ** Return 0 if point X,Y is outside the polygon 806 */ 807 static void geopolyContainsPointFunc( 808 sqlite3_context *context, 809 int argc, 810 sqlite3_value **argv 811 ){ 812 GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 813 double x0 = sqlite3_value_double(argv[1]); 814 double y0 = sqlite3_value_double(argv[2]); 815 int v = 0; 816 int cnt = 0; 817 int ii; 818 if( p1==0 ) return; 819 for(ii=0; ii<p1->nVertex-1; ii++){ 820 v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), 821 GeoX(p1,ii+1),GeoY(p1,ii+1)); 822 if( v==2 ) break; 823 cnt += v; 824 } 825 if( v!=2 ){ 826 v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii), 827 GeoX(p1,0), GeoY(p1,0)); 828 } 829 if( v==2 ){ 830 sqlite3_result_int(context, 1); 831 }else if( ((v+cnt)&1)==0 ){ 832 sqlite3_result_int(context, 0); 833 }else{ 834 sqlite3_result_int(context, 2); 835 } 836 sqlite3_free(p1); 837 } 838 839 /* Forward declaration */ 840 static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); 841 842 /* 843 ** SQL function: geopoly_within(P1,P2) 844 ** 845 ** Return +2 if P1 and P2 are the same polygon 846 ** Return +1 if P2 is contained within P1 847 ** Return 0 if any part of P2 is on the outside of P1 848 ** 849 */ 850 static void geopolyWithinFunc( 851 sqlite3_context *context, 852 int argc, 853 sqlite3_value **argv 854 ){ 855 GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 856 GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); 857 if( p1 && p2 ){ 858 int x = geopolyOverlap(p1, p2); 859 if( x<0 ){ 860 sqlite3_result_error_nomem(context); 861 }else{ 862 sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); 863 } 864 } 865 sqlite3_free(p1); 866 sqlite3_free(p2); 867 } 868 869 /* Objects used by the overlap algorihm. */ 870 typedef struct GeoEvent GeoEvent; 871 typedef struct GeoSegment GeoSegment; 872 typedef struct GeoOverlap GeoOverlap; 873 struct GeoEvent { 874 double x; /* X coordinate at which event occurs */ 875 int eType; /* 0 for ADD, 1 for REMOVE */ 876 GeoSegment *pSeg; /* The segment to be added or removed */ 877 GeoEvent *pNext; /* Next event in the sorted list */ 878 }; 879 struct GeoSegment { 880 double C, B; /* y = C*x + B */ 881 double y; /* Current y value */ 882 float y0; /* Initial y value */ 883 unsigned char side; /* 1 for p1, 2 for p2 */ 884 unsigned int idx; /* Which segment within the side */ 885 GeoSegment *pNext; /* Next segment in a list sorted by y */ 886 }; 887 struct GeoOverlap { 888 GeoEvent *aEvent; /* Array of all events */ 889 GeoSegment *aSegment; /* Array of all segments */ 890 int nEvent; /* Number of events */ 891 int nSegment; /* Number of segments */ 892 }; 893 894 /* 895 ** Add a single segment and its associated events. 896 */ 897 static void geopolyAddOneSegment( 898 GeoOverlap *p, 899 GeoCoord x0, 900 GeoCoord y0, 901 GeoCoord x1, 902 GeoCoord y1, 903 unsigned char side, 904 unsigned int idx 905 ){ 906 GeoSegment *pSeg; 907 GeoEvent *pEvent; 908 if( x0==x1 ) return; /* Ignore vertical segments */ 909 if( x0>x1 ){ 910 GeoCoord t = x0; 911 x0 = x1; 912 x1 = t; 913 t = y0; 914 y0 = y1; 915 y1 = t; 916 } 917 pSeg = p->aSegment + p->nSegment; 918 p->nSegment++; 919 pSeg->C = (y1-y0)/(x1-x0); 920 pSeg->B = y1 - x1*pSeg->C; 921 pSeg->y0 = y0; 922 pSeg->side = side; 923 pSeg->idx = idx; 924 pEvent = p->aEvent + p->nEvent; 925 p->nEvent++; 926 pEvent->x = x0; 927 pEvent->eType = 0; 928 pEvent->pSeg = pSeg; 929 pEvent = p->aEvent + p->nEvent; 930 p->nEvent++; 931 pEvent->x = x1; 932 pEvent->eType = 1; 933 pEvent->pSeg = pSeg; 934 } 935 936 937 938 /* 939 ** Insert all segments and events for polygon pPoly. 940 */ 941 static void geopolyAddSegments( 942 GeoOverlap *p, /* Add segments to this Overlap object */ 943 GeoPoly *pPoly, /* Take all segments from this polygon */ 944 unsigned char side /* The side of pPoly */ 945 ){ 946 unsigned int i; 947 GeoCoord *x; 948 for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ 949 x = &GeoX(pPoly,i); 950 geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); 951 } 952 x = &GeoX(pPoly,i); 953 geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); 954 } 955 956 /* 957 ** Merge two lists of sorted events by X coordinate 958 */ 959 static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ 960 GeoEvent head, *pLast; 961 head.pNext = 0; 962 pLast = &head; 963 while( pRight && pLeft ){ 964 if( pRight->x <= pLeft->x ){ 965 pLast->pNext = pRight; 966 pLast = pRight; 967 pRight = pRight->pNext; 968 }else{ 969 pLast->pNext = pLeft; 970 pLast = pLeft; 971 pLeft = pLeft->pNext; 972 } 973 } 974 pLast->pNext = pRight ? pRight : pLeft; 975 return head.pNext; 976 } 977 978 /* 979 ** Sort an array of nEvent event objects into a list. 980 */ 981 static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ 982 int mx = 0; 983 int i, j; 984 GeoEvent *p; 985 GeoEvent *a[50]; 986 for(i=0; i<nEvent; i++){ 987 p = &aEvent[i]; 988 p->pNext = 0; 989 for(j=0; j<mx && a[j]; j++){ 990 p = geopolyEventMerge(a[j], p); 991 a[j] = 0; 992 } 993 a[j] = p; 994 if( j>=mx ) mx = j+1; 995 } 996 p = 0; 997 for(i=0; i<mx; i++){ 998 p = geopolyEventMerge(a[i], p); 999 } 1000 return p; 1001 } 1002 1003 /* 1004 ** Merge two lists of sorted segments by Y, and then by C. 1005 */ 1006 static GeoSegment *geopolySegmentMerge(GeoSegment *pLeft, GeoSegment *pRight){ 1007 GeoSegment head, *pLast; 1008 head.pNext = 0; 1009 pLast = &head; 1010 while( pRight && pLeft ){ 1011 double r = pRight->y - pLeft->y; 1012 if( r==0.0 ) r = pRight->C - pLeft->C; 1013 if( r<0.0 ){ 1014 pLast->pNext = pRight; 1015 pLast = pRight; 1016 pRight = pRight->pNext; 1017 }else{ 1018 pLast->pNext = pLeft; 1019 pLast = pLeft; 1020 pLeft = pLeft->pNext; 1021 } 1022 } 1023 pLast->pNext = pRight ? pRight : pLeft; 1024 return head.pNext; 1025 } 1026 1027 /* 1028 ** Sort a list of GeoSegments in order of increasing Y and in the event of 1029 ** a tie, increasing C (slope). 1030 */ 1031 static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ 1032 int mx = 0; 1033 int i; 1034 GeoSegment *p; 1035 GeoSegment *a[50]; 1036 while( pList ){ 1037 p = pList; 1038 pList = pList->pNext; 1039 p->pNext = 0; 1040 for(i=0; i<mx && a[i]; i++){ 1041 p = geopolySegmentMerge(a[i], p); 1042 a[i] = 0; 1043 } 1044 a[i] = p; 1045 if( i>=mx ) mx = i+1; 1046 } 1047 p = 0; 1048 for(i=0; i<mx; i++){ 1049 p = geopolySegmentMerge(a[i], p); 1050 } 1051 return p; 1052 } 1053 1054 /* 1055 ** Determine the overlap between two polygons 1056 */ 1057 static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ 1058 sqlite3_int64 nVertex = p1->nVertex + p2->nVertex + 2; 1059 GeoOverlap *p; 1060 sqlite3_int64 nByte; 1061 GeoEvent *pThisEvent; 1062 double rX; 1063 int rc = 0; 1064 int needSort = 0; 1065 GeoSegment *pActive = 0; 1066 GeoSegment *pSeg; 1067 unsigned char aOverlap[4]; 1068 1069 nByte = sizeof(GeoEvent)*nVertex*2 1070 + sizeof(GeoSegment)*nVertex 1071 + sizeof(GeoOverlap); 1072 p = sqlite3_malloc64( nByte ); 1073 if( p==0 ) return -1; 1074 p->aEvent = (GeoEvent*)&p[1]; 1075 p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; 1076 p->nEvent = p->nSegment = 0; 1077 geopolyAddSegments(p, p1, 1); 1078 geopolyAddSegments(p, p2, 2); 1079 pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); 1080 rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0; 1081 memset(aOverlap, 0, sizeof(aOverlap)); 1082 while( pThisEvent ){ 1083 if( pThisEvent->x!=rX ){ 1084 GeoSegment *pPrev = 0; 1085 int iMask = 0; 1086 GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); 1087 rX = pThisEvent->x; 1088 if( needSort ){ 1089 GEODEBUG(("SORT\n")); 1090 pActive = geopolySortSegmentsByYAndC(pActive); 1091 needSort = 0; 1092 } 1093 for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 1094 if( pPrev ){ 1095 if( pPrev->y!=pSeg->y ){ 1096 GEODEBUG(("MASK: %d\n", iMask)); 1097 aOverlap[iMask] = 1; 1098 } 1099 } 1100 iMask ^= pSeg->side; 1101 pPrev = pSeg; 1102 } 1103 pPrev = 0; 1104 for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 1105 double y = pSeg->C*rX + pSeg->B; 1106 GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); 1107 pSeg->y = y; 1108 if( pPrev ){ 1109 if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ 1110 rc = 1; 1111 GEODEBUG(("Crossing: %d.%d and %d.%d\n", 1112 pPrev->side, pPrev->idx, 1113 pSeg->side, pSeg->idx)); 1114 goto geopolyOverlapDone; 1115 }else if( pPrev->y!=pSeg->y ){ 1116 GEODEBUG(("MASK: %d\n", iMask)); 1117 aOverlap[iMask] = 1; 1118 } 1119 } 1120 iMask ^= pSeg->side; 1121 pPrev = pSeg; 1122 } 1123 } 1124 GEODEBUG(("%s %d.%d C=%g B=%g\n", 1125 pThisEvent->eType ? "RM " : "ADD", 1126 pThisEvent->pSeg->side, pThisEvent->pSeg->idx, 1127 pThisEvent->pSeg->C, 1128 pThisEvent->pSeg->B)); 1129 if( pThisEvent->eType==0 ){ 1130 /* Add a segment */ 1131 pSeg = pThisEvent->pSeg; 1132 pSeg->y = pSeg->y0; 1133 pSeg->pNext = pActive; 1134 pActive = pSeg; 1135 needSort = 1; 1136 }else{ 1137 /* Remove a segment */ 1138 if( pActive==pThisEvent->pSeg ){ 1139 pActive = ALWAYS(pActive) ? pActive->pNext : 0; 1140 }else{ 1141 for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 1142 if( pSeg->pNext==pThisEvent->pSeg ){ 1143 pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0; 1144 break; 1145 } 1146 } 1147 } 1148 } 1149 pThisEvent = pThisEvent->pNext; 1150 } 1151 if( aOverlap[3]==0 ){ 1152 rc = 0; 1153 }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ 1154 rc = 3; 1155 }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ 1156 rc = 2; 1157 }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ 1158 rc = 4; 1159 }else{ 1160 rc = 1; 1161 } 1162 1163 geopolyOverlapDone: 1164 sqlite3_free(p); 1165 return rc; 1166 } 1167 1168 /* 1169 ** SQL function: geopoly_overlap(P1,P2) 1170 ** 1171 ** Determine whether or not P1 and P2 overlap. Return value: 1172 ** 1173 ** 0 The two polygons are disjoint 1174 ** 1 They overlap 1175 ** 2 P1 is completely contained within P2 1176 ** 3 P2 is completely contained within P1 1177 ** 4 P1 and P2 are the same polygon 1178 ** NULL Either P1 or P2 or both are not valid polygons 1179 */ 1180 static void geopolyOverlapFunc( 1181 sqlite3_context *context, 1182 int argc, 1183 sqlite3_value **argv 1184 ){ 1185 GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 1186 GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); 1187 if( p1 && p2 ){ 1188 int x = geopolyOverlap(p1, p2); 1189 if( x<0 ){ 1190 sqlite3_result_error_nomem(context); 1191 }else{ 1192 sqlite3_result_int(context, x); 1193 } 1194 } 1195 sqlite3_free(p1); 1196 sqlite3_free(p2); 1197 } 1198 1199 /* 1200 ** Enable or disable debugging output 1201 */ 1202 static void geopolyDebugFunc( 1203 sqlite3_context *context, 1204 int argc, 1205 sqlite3_value **argv 1206 ){ 1207 #ifdef GEOPOLY_ENABLE_DEBUG 1208 geo_debug = sqlite3_value_int(argv[0]); 1209 #endif 1210 } 1211 1212 /* 1213 ** This function is the implementation of both the xConnect and xCreate 1214 ** methods of the geopoly virtual table. 1215 ** 1216 ** argv[0] -> module name 1217 ** argv[1] -> database name 1218 ** argv[2] -> table name 1219 ** argv[...] -> column names... 1220 */ 1221 static int geopolyInit( 1222 sqlite3 *db, /* Database connection */ 1223 void *pAux, /* One of the RTREE_COORD_* constants */ 1224 int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ 1225 sqlite3_vtab **ppVtab, /* OUT: New virtual table */ 1226 char **pzErr, /* OUT: Error message, if any */ 1227 int isCreate /* True for xCreate, false for xConnect */ 1228 ){ 1229 int rc = SQLITE_OK; 1230 Rtree *pRtree; 1231 sqlite3_int64 nDb; /* Length of string argv[1] */ 1232 sqlite3_int64 nName; /* Length of string argv[2] */ 1233 sqlite3_str *pSql; 1234 char *zSql; 1235 int ii; 1236 1237 sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); 1238 1239 /* Allocate the sqlite3_vtab structure */ 1240 nDb = strlen(argv[1]); 1241 nName = strlen(argv[2]); 1242 pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2); 1243 if( !pRtree ){ 1244 return SQLITE_NOMEM; 1245 } 1246 memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); 1247 pRtree->nBusy = 1; 1248 pRtree->base.pModule = &rtreeModule; 1249 pRtree->zDb = (char *)&pRtree[1]; 1250 pRtree->zName = &pRtree->zDb[nDb+1]; 1251 pRtree->eCoordType = RTREE_COORD_REAL32; 1252 pRtree->nDim = 2; 1253 pRtree->nDim2 = 4; 1254 memcpy(pRtree->zDb, argv[1], nDb); 1255 memcpy(pRtree->zName, argv[2], nName); 1256 1257 1258 /* Create/Connect to the underlying relational database schema. If 1259 ** that is successful, call sqlite3_declare_vtab() to configure 1260 ** the r-tree table schema. 1261 */ 1262 pSql = sqlite3_str_new(db); 1263 sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); 1264 pRtree->nAux = 1; /* Add one for _shape */ 1265 pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ 1266 for(ii=3; ii<argc; ii++){ 1267 pRtree->nAux++; 1268 sqlite3_str_appendf(pSql, ",%s", argv[ii]); 1269 } 1270 sqlite3_str_appendf(pSql, ");"); 1271 zSql = sqlite3_str_finish(pSql); 1272 if( !zSql ){ 1273 rc = SQLITE_NOMEM; 1274 }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ 1275 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 1276 } 1277 sqlite3_free(zSql); 1278 if( rc ) goto geopolyInit_fail; 1279 pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; 1280 1281 /* Figure out the node size to use. */ 1282 rc = getNodeSize(db, pRtree, isCreate, pzErr); 1283 if( rc ) goto geopolyInit_fail; 1284 rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); 1285 if( rc ){ 1286 *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 1287 goto geopolyInit_fail; 1288 } 1289 1290 *ppVtab = (sqlite3_vtab *)pRtree; 1291 return SQLITE_OK; 1292 1293 geopolyInit_fail: 1294 if( rc==SQLITE_OK ) rc = SQLITE_ERROR; 1295 assert( *ppVtab==0 ); 1296 assert( pRtree->nBusy==1 ); 1297 rtreeRelease(pRtree); 1298 return rc; 1299 } 1300 1301 1302 /* 1303 ** GEOPOLY virtual table module xCreate method. 1304 */ 1305 static int geopolyCreate( 1306 sqlite3 *db, 1307 void *pAux, 1308 int argc, const char *const*argv, 1309 sqlite3_vtab **ppVtab, 1310 char **pzErr 1311 ){ 1312 return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); 1313 } 1314 1315 /* 1316 ** GEOPOLY virtual table module xConnect method. 1317 */ 1318 static int geopolyConnect( 1319 sqlite3 *db, 1320 void *pAux, 1321 int argc, const char *const*argv, 1322 sqlite3_vtab **ppVtab, 1323 char **pzErr 1324 ){ 1325 return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); 1326 } 1327 1328 1329 /* 1330 ** GEOPOLY virtual table module xFilter method. 1331 ** 1332 ** Query plans: 1333 ** 1334 ** 1 rowid lookup 1335 ** 2 search for objects overlapping the same bounding box 1336 ** that contains polygon argv[0] 1337 ** 3 search for objects overlapping the same bounding box 1338 ** that contains polygon argv[0] 1339 ** 4 full table scan 1340 */ 1341 static int geopolyFilter( 1342 sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ 1343 int idxNum, /* Query plan */ 1344 const char *idxStr, /* Not Used */ 1345 int argc, sqlite3_value **argv /* Parameters to the query plan */ 1346 ){ 1347 Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; 1348 RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; 1349 RtreeNode *pRoot = 0; 1350 int rc = SQLITE_OK; 1351 int iCell = 0; 1352 1353 rtreeReference(pRtree); 1354 1355 /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ 1356 resetCursor(pCsr); 1357 1358 pCsr->iStrategy = idxNum; 1359 if( idxNum==1 ){ 1360 /* Special case - lookup by rowid. */ 1361 RtreeNode *pLeaf; /* Leaf on which the required cell resides */ 1362 RtreeSearchPoint *p; /* Search point for the leaf */ 1363 i64 iRowid = sqlite3_value_int64(argv[0]); 1364 i64 iNode = 0; 1365 rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); 1366 if( rc==SQLITE_OK && pLeaf!=0 ){ 1367 p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); 1368 assert( p!=0 ); /* Always returns pCsr->sPoint */ 1369 pCsr->aNode[0] = pLeaf; 1370 p->id = iNode; 1371 p->eWithin = PARTLY_WITHIN; 1372 rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); 1373 p->iCell = (u8)iCell; 1374 RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); 1375 }else{ 1376 pCsr->atEOF = 1; 1377 } 1378 }else{ 1379 /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 1380 ** with the configured constraints. 1381 */ 1382 rc = nodeAcquire(pRtree, 1, 0, &pRoot); 1383 if( rc==SQLITE_OK && idxNum<=3 ){ 1384 RtreeCoord bbox[4]; 1385 RtreeConstraint *p; 1386 assert( argc==1 ); 1387 assert( argv[0]!=0 ); 1388 geopolyBBox(0, argv[0], bbox, &rc); 1389 if( rc ){ 1390 goto geopoly_filter_end; 1391 } 1392 pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); 1393 pCsr->nConstraint = 4; 1394 if( p==0 ){ 1395 rc = SQLITE_NOMEM; 1396 }else{ 1397 memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); 1398 memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); 1399 if( idxNum==2 ){ 1400 /* Overlap query */ 1401 p->op = 'B'; 1402 p->iCoord = 0; 1403 p->u.rValue = bbox[1].f; 1404 p++; 1405 p->op = 'D'; 1406 p->iCoord = 1; 1407 p->u.rValue = bbox[0].f; 1408 p++; 1409 p->op = 'B'; 1410 p->iCoord = 2; 1411 p->u.rValue = bbox[3].f; 1412 p++; 1413 p->op = 'D'; 1414 p->iCoord = 3; 1415 p->u.rValue = bbox[2].f; 1416 }else{ 1417 /* Within query */ 1418 p->op = 'D'; 1419 p->iCoord = 0; 1420 p->u.rValue = bbox[0].f; 1421 p++; 1422 p->op = 'B'; 1423 p->iCoord = 1; 1424 p->u.rValue = bbox[1].f; 1425 p++; 1426 p->op = 'D'; 1427 p->iCoord = 2; 1428 p->u.rValue = bbox[2].f; 1429 p++; 1430 p->op = 'B'; 1431 p->iCoord = 3; 1432 p->u.rValue = bbox[3].f; 1433 } 1434 } 1435 } 1436 if( rc==SQLITE_OK ){ 1437 RtreeSearchPoint *pNew; 1438 pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); 1439 if( pNew==0 ){ 1440 rc = SQLITE_NOMEM; 1441 goto geopoly_filter_end; 1442 } 1443 pNew->id = 1; 1444 pNew->iCell = 0; 1445 pNew->eWithin = PARTLY_WITHIN; 1446 assert( pCsr->bPoint==1 ); 1447 pCsr->aNode[0] = pRoot; 1448 pRoot = 0; 1449 RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); 1450 rc = rtreeStepToLeaf(pCsr); 1451 } 1452 } 1453 1454 geopoly_filter_end: 1455 nodeRelease(pRtree, pRoot); 1456 rtreeRelease(pRtree); 1457 return rc; 1458 } 1459 1460 /* 1461 ** Rtree virtual table module xBestIndex method. There are three 1462 ** table scan strategies to choose from (in order from most to 1463 ** least desirable): 1464 ** 1465 ** idxNum idxStr Strategy 1466 ** ------------------------------------------------ 1467 ** 1 "rowid" Direct lookup by rowid. 1468 ** 2 "rtree" R-tree overlap query using geopoly_overlap() 1469 ** 3 "rtree" R-tree within query using geopoly_within() 1470 ** 4 "fullscan" full-table scan. 1471 ** ------------------------------------------------ 1472 */ 1473 static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ 1474 int ii; 1475 int iRowidTerm = -1; 1476 int iFuncTerm = -1; 1477 int idxNum = 0; 1478 1479 for(ii=0; ii<pIdxInfo->nConstraint; ii++){ 1480 struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; 1481 if( !p->usable ) continue; 1482 if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ 1483 iRowidTerm = ii; 1484 break; 1485 } 1486 if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ 1487 /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() 1488 ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). 1489 ** See geopolyFindFunction() */ 1490 iFuncTerm = ii; 1491 idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; 1492 } 1493 } 1494 1495 if( iRowidTerm>=0 ){ 1496 pIdxInfo->idxNum = 1; 1497 pIdxInfo->idxStr = "rowid"; 1498 pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; 1499 pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; 1500 pIdxInfo->estimatedCost = 30.0; 1501 pIdxInfo->estimatedRows = 1; 1502 pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; 1503 return SQLITE_OK; 1504 } 1505 if( iFuncTerm>=0 ){ 1506 pIdxInfo->idxNum = idxNum; 1507 pIdxInfo->idxStr = "rtree"; 1508 pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; 1509 pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; 1510 pIdxInfo->estimatedCost = 300.0; 1511 pIdxInfo->estimatedRows = 10; 1512 return SQLITE_OK; 1513 } 1514 pIdxInfo->idxNum = 4; 1515 pIdxInfo->idxStr = "fullscan"; 1516 pIdxInfo->estimatedCost = 3000000.0; 1517 pIdxInfo->estimatedRows = 100000; 1518 return SQLITE_OK; 1519 } 1520 1521 1522 /* 1523 ** GEOPOLY virtual table module xColumn method. 1524 */ 1525 static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ 1526 Rtree *pRtree = (Rtree *)cur->pVtab; 1527 RtreeCursor *pCsr = (RtreeCursor *)cur; 1528 RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); 1529 int rc = SQLITE_OK; 1530 RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); 1531 1532 if( rc ) return rc; 1533 if( p==0 ) return SQLITE_OK; 1534 if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; 1535 if( i<=pRtree->nAux ){ 1536 if( !pCsr->bAuxValid ){ 1537 if( pCsr->pReadAux==0 ){ 1538 rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, 1539 &pCsr->pReadAux, 0); 1540 if( rc ) return rc; 1541 } 1542 sqlite3_bind_int64(pCsr->pReadAux, 1, 1543 nodeGetRowid(pRtree, pNode, p->iCell)); 1544 rc = sqlite3_step(pCsr->pReadAux); 1545 if( rc==SQLITE_ROW ){ 1546 pCsr->bAuxValid = 1; 1547 }else{ 1548 sqlite3_reset(pCsr->pReadAux); 1549 if( rc==SQLITE_DONE ) rc = SQLITE_OK; 1550 return rc; 1551 } 1552 } 1553 sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); 1554 } 1555 return SQLITE_OK; 1556 } 1557 1558 1559 /* 1560 ** The xUpdate method for GEOPOLY module virtual tables. 1561 ** 1562 ** For DELETE: 1563 ** 1564 ** argv[0] = the rowid to be deleted 1565 ** 1566 ** For INSERT: 1567 ** 1568 ** argv[0] = SQL NULL 1569 ** argv[1] = rowid to insert, or an SQL NULL to select automatically 1570 ** argv[2] = _shape column 1571 ** argv[3] = first application-defined column.... 1572 ** 1573 ** For UPDATE: 1574 ** 1575 ** argv[0] = rowid to modify. Never NULL 1576 ** argv[1] = rowid after the change. Never NULL 1577 ** argv[2] = new value for _shape 1578 ** argv[3] = new value for first application-defined column.... 1579 */ 1580 static int geopolyUpdate( 1581 sqlite3_vtab *pVtab, 1582 int nData, 1583 sqlite3_value **aData, 1584 sqlite_int64 *pRowid 1585 ){ 1586 Rtree *pRtree = (Rtree *)pVtab; 1587 int rc = SQLITE_OK; 1588 RtreeCell cell; /* New cell to insert if nData>1 */ 1589 i64 oldRowid; /* The old rowid */ 1590 int oldRowidValid; /* True if oldRowid is valid */ 1591 i64 newRowid; /* The new rowid */ 1592 int newRowidValid; /* True if newRowid is valid */ 1593 int coordChange = 0; /* Change in coordinates */ 1594 1595 if( pRtree->nNodeRef ){ 1596 /* Unable to write to the btree while another cursor is reading from it, 1597 ** since the write might do a rebalance which would disrupt the read 1598 ** cursor. */ 1599 return SQLITE_LOCKED_VTAB; 1600 } 1601 rtreeReference(pRtree); 1602 assert(nData>=1); 1603 1604 oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; 1605 oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; 1606 newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; 1607 newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; 1608 cell.iRowid = newRowid; 1609 1610 if( nData>1 /* not a DELETE */ 1611 && (!oldRowidValid /* INSERT */ 1612 || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ 1613 || oldRowid!=newRowid) /* Rowid change */ 1614 ){ 1615 assert( aData[2]!=0 ); 1616 geopolyBBox(0, aData[2], cell.aCoord, &rc); 1617 if( rc ){ 1618 if( rc==SQLITE_ERROR ){ 1619 pVtab->zErrMsg = 1620 sqlite3_mprintf("_shape does not contain a valid polygon"); 1621 } 1622 goto geopoly_update_end; 1623 } 1624 coordChange = 1; 1625 1626 /* If a rowid value was supplied, check if it is already present in 1627 ** the table. If so, the constraint has failed. */ 1628 if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ 1629 int steprc; 1630 sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); 1631 steprc = sqlite3_step(pRtree->pReadRowid); 1632 rc = sqlite3_reset(pRtree->pReadRowid); 1633 if( SQLITE_ROW==steprc ){ 1634 if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ 1635 rc = rtreeDeleteRowid(pRtree, cell.iRowid); 1636 }else{ 1637 rc = rtreeConstraintError(pRtree, 0); 1638 } 1639 } 1640 } 1641 } 1642 1643 /* If aData[0] is not an SQL NULL value, it is the rowid of a 1644 ** record to delete from the r-tree table. The following block does 1645 ** just that. 1646 */ 1647 if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ 1648 rc = rtreeDeleteRowid(pRtree, oldRowid); 1649 } 1650 1651 /* If the aData[] array contains more than one element, elements 1652 ** (aData[2]..aData[argc-1]) contain a new record to insert into 1653 ** the r-tree structure. 1654 */ 1655 if( rc==SQLITE_OK && nData>1 && coordChange ){ 1656 /* Insert the new record into the r-tree */ 1657 RtreeNode *pLeaf = 0; 1658 if( !newRowidValid ){ 1659 rc = rtreeNewRowid(pRtree, &cell.iRowid); 1660 } 1661 *pRowid = cell.iRowid; 1662 if( rc==SQLITE_OK ){ 1663 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); 1664 } 1665 if( rc==SQLITE_OK ){ 1666 int rc2; 1667 pRtree->iReinsertHeight = -1; 1668 rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); 1669 rc2 = nodeRelease(pRtree, pLeaf); 1670 if( rc==SQLITE_OK ){ 1671 rc = rc2; 1672 } 1673 } 1674 } 1675 1676 /* Change the data */ 1677 if( rc==SQLITE_OK && nData>1 ){ 1678 sqlite3_stmt *pUp = pRtree->pWriteAux; 1679 int jj; 1680 int nChange = 0; 1681 sqlite3_bind_int64(pUp, 1, cell.iRowid); 1682 assert( pRtree->nAux>=1 ); 1683 if( sqlite3_value_nochange(aData[2]) ){ 1684 sqlite3_bind_null(pUp, 2); 1685 }else{ 1686 GeoPoly *p = 0; 1687 if( sqlite3_value_type(aData[2])==SQLITE_TEXT 1688 && (p = geopolyFuncParam(0, aData[2], &rc))!=0 1689 && rc==SQLITE_OK 1690 ){ 1691 sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); 1692 }else{ 1693 sqlite3_bind_value(pUp, 2, aData[2]); 1694 } 1695 sqlite3_free(p); 1696 nChange = 1; 1697 } 1698 for(jj=1; jj<nData-2; jj++){ 1699 nChange++; 1700 sqlite3_bind_value(pUp, jj+2, aData[jj+2]); 1701 } 1702 if( nChange ){ 1703 sqlite3_step(pUp); 1704 rc = sqlite3_reset(pUp); 1705 } 1706 } 1707 1708 geopoly_update_end: 1709 rtreeRelease(pRtree); 1710 return rc; 1711 } 1712 1713 /* 1714 ** Report that geopoly_overlap() is an overloaded function suitable 1715 ** for use in xBestIndex. 1716 */ 1717 static int geopolyFindFunction( 1718 sqlite3_vtab *pVtab, 1719 int nArg, 1720 const char *zName, 1721 void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), 1722 void **ppArg 1723 ){ 1724 if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){ 1725 *pxFunc = geopolyOverlapFunc; 1726 *ppArg = 0; 1727 return SQLITE_INDEX_CONSTRAINT_FUNCTION; 1728 } 1729 if( sqlite3_stricmp(zName, "geopoly_within")==0 ){ 1730 *pxFunc = geopolyWithinFunc; 1731 *ppArg = 0; 1732 return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; 1733 } 1734 return 0; 1735 } 1736 1737 1738 static sqlite3_module geopolyModule = { 1739 3, /* iVersion */ 1740 geopolyCreate, /* xCreate - create a table */ 1741 geopolyConnect, /* xConnect - connect to an existing table */ 1742 geopolyBestIndex, /* xBestIndex - Determine search strategy */ 1743 rtreeDisconnect, /* xDisconnect - Disconnect from a table */ 1744 rtreeDestroy, /* xDestroy - Drop a table */ 1745 rtreeOpen, /* xOpen - open a cursor */ 1746 rtreeClose, /* xClose - close a cursor */ 1747 geopolyFilter, /* xFilter - configure scan constraints */ 1748 rtreeNext, /* xNext - advance a cursor */ 1749 rtreeEof, /* xEof */ 1750 geopolyColumn, /* xColumn - read data */ 1751 rtreeRowid, /* xRowid - read data */ 1752 geopolyUpdate, /* xUpdate - write data */ 1753 rtreeBeginTransaction, /* xBegin - begin transaction */ 1754 rtreeEndTransaction, /* xSync - sync transaction */ 1755 rtreeEndTransaction, /* xCommit - commit transaction */ 1756 rtreeEndTransaction, /* xRollback - rollback transaction */ 1757 geopolyFindFunction, /* xFindFunction - function overloading */ 1758 rtreeRename, /* xRename - rename the table */ 1759 rtreeSavepoint, /* xSavepoint */ 1760 0, /* xRelease */ 1761 0, /* xRollbackTo */ 1762 rtreeShadowName /* xShadowName */ 1763 }; 1764 1765 static int sqlite3_geopoly_init(sqlite3 *db){ 1766 int rc = SQLITE_OK; 1767 static const struct { 1768 void (*xFunc)(sqlite3_context*,int,sqlite3_value**); 1769 signed char nArg; 1770 unsigned char bPure; 1771 const char *zName; 1772 } aFunc[] = { 1773 { geopolyAreaFunc, 1, 1, "geopoly_area" }, 1774 { geopolyBlobFunc, 1, 1, "geopoly_blob" }, 1775 { geopolyJsonFunc, 1, 1, "geopoly_json" }, 1776 { geopolySvgFunc, -1, 1, "geopoly_svg" }, 1777 { geopolyWithinFunc, 2, 1, "geopoly_within" }, 1778 { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, 1779 { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, 1780 { geopolyDebugFunc, 1, 0, "geopoly_debug" }, 1781 { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, 1782 { geopolyXformFunc, 7, 1, "geopoly_xform" }, 1783 { geopolyRegularFunc, 4, 1, "geopoly_regular" }, 1784 { geopolyCcwFunc, 1, 1, "geopoly_ccw" }, 1785 }; 1786 static const struct { 1787 void (*xStep)(sqlite3_context*,int,sqlite3_value**); 1788 void (*xFinal)(sqlite3_context*); 1789 const char *zName; 1790 } aAgg[] = { 1791 { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" }, 1792 }; 1793 int i; 1794 for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ 1795 int enc; 1796 if( aFunc[i].bPure ){ 1797 enc = SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS; 1798 }else{ 1799 enc = SQLITE_UTF8|SQLITE_DIRECTONLY; 1800 } 1801 rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, 1802 enc, 0, 1803 aFunc[i].xFunc, 0, 0); 1804 } 1805 for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ 1806 rc = sqlite3_create_function(db, aAgg[i].zName, 1, 1807 SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, 0, 1808 0, aAgg[i].xStep, aAgg[i].xFinal); 1809 } 1810 if( rc==SQLITE_OK ){ 1811 rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0); 1812 } 1813 return rc; 1814 } 1815