Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch alter-table-rename-table Excluding Merge-Ins
This is equivalent to a diff from 62089c6d to 8d89ddc1
2018-09-01
| ||
16:13 | Merge alter-table-rename-table back into this branch. (check-in: ad704a7c user: dan tags: alter-table-rename-column) | |
16:05 | Have "ALTER TABLE ADD COLUMN" reload the entire db schema, as "RENAME COLUMN" and "RENAME TABLE" do. (Closed-Leaf check-in: 8d89ddc1 user: dan tags: alter-table-rename-table) | |
15:55 | Merge fixes from the alter-table-rename-column branch that occurred after this branch separated from that one. (check-in: 22e785aa user: drh tags: alter-table-rename-table) | |
2018-08-25
| ||
16:22 | Fix a minor issue in the altercol.test script so that it runs on Windows. (check-in: 62089c6d user: drh tags: alter-table-rename-column) | |
16:14 | Invoke the authorizer for ALTER TABLE RENAME COLUMN. (check-in: fc293bcb user: drh tags: alter-table-rename-column) | |
Changes to Makefile.in.
346 346 $(TOP)/ext/fts3/fts3_unicode2.c \ 347 347 $(TOP)/ext/fts3/fts3_write.c 348 348 SRC += \ 349 349 $(TOP)/ext/icu/sqliteicu.h \ 350 350 $(TOP)/ext/icu/icu.c 351 351 SRC += \ 352 352 $(TOP)/ext/rtree/rtree.h \ 353 - $(TOP)/ext/rtree/rtree.c 353 + $(TOP)/ext/rtree/rtree.c \ 354 + $(TOP)/ext/rtree/geopoly.c 354 355 SRC += \ 355 356 $(TOP)/ext/session/sqlite3session.c \ 356 357 $(TOP)/ext/session/sqlite3session.h 357 358 SRC += \ 358 359 $(TOP)/ext/rbu/sqlite3rbu.h \ 359 360 $(TOP)/ext/rbu/sqlite3rbu.c 360 361 SRC += \ ................................................................................ 548 549 $(TOP)/ext/fts2/fts2_tokenizer.h 549 550 EXTHDR += \ 550 551 $(TOP)/ext/fts3/fts3.h \ 551 552 $(TOP)/ext/fts3/fts3Int.h \ 552 553 $(TOP)/ext/fts3/fts3_hash.h \ 553 554 $(TOP)/ext/fts3/fts3_tokenizer.h 554 555 EXTHDR += \ 555 - $(TOP)/ext/rtree/rtree.h 556 + $(TOP)/ext/rtree/rtree.h \ 557 + $(TOP)/ext/rtree/geopoly.c 556 558 EXTHDR += \ 557 559 $(TOP)/ext/icu/sqliteicu.h 558 560 EXTHDR += \ 559 561 $(TOP)/ext/rtree/sqlite3rtree.h 560 562 561 563 # executables needed for testing 562 564 #
Changes to Makefile.msc.
334 334 335 335 # These are the "standard" SQLite compilation options used when compiling for 336 336 # the Windows platform. 337 337 # 338 338 !IFNDEF OPT_FEATURE_FLAGS 339 339 !IF $(MINIMAL_AMALGAMATION)==0 340 340 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 341 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 341 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 342 342 !ENDIF 343 343 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 344 344 !ENDIF 345 345 346 346 # Should the session extension be enabled? If so, add compilation options 347 347 # to enable it. 348 348 # ................................................................................ 1409 1409 SRC09 = \ 1410 1410 $(TOP)\ext\fts3\fts3.h \ 1411 1411 $(TOP)\ext\fts3\fts3Int.h \ 1412 1412 $(TOP)\ext\fts3\fts3_hash.h \ 1413 1413 $(TOP)\ext\fts3\fts3_tokenizer.h \ 1414 1414 $(TOP)\ext\icu\sqliteicu.h \ 1415 1415 $(TOP)\ext\rtree\rtree.h \ 1416 + $(TOP)\ext\rtree\geopoly.c \ 1416 1417 $(TOP)\ext\rbu\sqlite3rbu.h \ 1417 1418 $(TOP)\ext\session\sqlite3session.h 1418 1419 1419 1420 # Generated source code files 1420 1421 # 1421 1422 SRC10 = \ 1422 1423 opcodes.c \ ................................................................................ 1583 1584 $(TOP)\ext\fts2\fts2_tokenizer.h 1584 1585 EXTHDR = $(EXTHDR) \ 1585 1586 $(TOP)\ext\fts3\fts3.h \ 1586 1587 $(TOP)\ext\fts3\fts3Int.h \ 1587 1588 $(TOP)\ext\fts3\fts3_hash.h \ 1588 1589 $(TOP)\ext\fts3\fts3_tokenizer.h 1589 1590 EXTHDR = $(EXTHDR) \ 1590 - $(TOP)\ext\rtree\rtree.h 1591 + $(TOP)\ext\rtree\rtree.h \ 1592 + $(TOP)\ext\rtree\geopoly.c 1591 1593 EXTHDR = $(EXTHDR) \ 1592 1594 $(TOP)\ext\icu\sqliteicu.h 1593 1595 EXTHDR = $(EXTHDR) \ 1594 1596 $(TOP)\ext\rtree\sqlite3rtree.h 1595 1597 EXTHDR = $(EXTHDR) \ 1596 1598 $(TOP)\ext\session\sqlite3session.h 1597 1599
Changes to README.md.
1 1 <h1 align="center">SQLite Source Repository</h1> 2 2 3 -This repository contains the complete source code for the SQLite database 4 -engine. Some test scripts are also included. However, many other test scripts 3 +This repository contains the complete source code for the 4 +[SQLite database engine](https://sqlite.org/). Some test scripts 5 +are also included. However, many other test scripts 5 6 and most of the documentation are managed separately. 6 7 7 8 SQLite [does not use Git](https://sqlite.org/whynotgit.html). 8 9 If you are reading this on GitHub, then you are looking at an 9 10 unofficial mirror. See <https://sqlite.org/src> for the official 10 11 repository. 11 12
Changes to configure.
907 907 enable_memsys5 908 908 enable_memsys3 909 909 enable_fts3 910 910 enable_fts4 911 911 enable_fts5 912 912 enable_json1 913 913 enable_update_limit 914 +enable_geopoly 914 915 enable_rtree 915 916 enable_session 916 917 enable_gcov 917 918 ' 918 919 ac_precious_vars='build_alias 919 920 host_alias 920 921 target_alias ................................................................................ 1559 1560 --enable-memsys5 Enable MEMSYS5 1560 1561 --enable-memsys3 Enable MEMSYS3 1561 1562 --enable-fts3 Enable the FTS3 extension 1562 1563 --enable-fts4 Enable the FTS4 extension 1563 1564 --enable-fts5 Enable the FTS5 extension 1564 1565 --enable-json1 Enable the JSON1 extension 1565 1566 --enable-update-limit Enable the UPDATE/DELETE LIMIT clause 1567 + --enable-geopoly Enable the GEOPOLY extension 1566 1568 --enable-rtree Enable the RTREE extension 1567 1569 --enable-session Enable the SESSION extension 1568 1570 --enable-gcov Enable coverage testing using gcov 1569 1571 1570 1572 Optional Packages: 1571 1573 --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] 1572 1574 --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) ................................................................................ 3928 3930 { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 3929 3931 $as_echo_n "checking the name lister ($NM) interface... " >&6; } 3930 3932 if ${lt_cv_nm_interface+:} false; then : 3931 3933 $as_echo_n "(cached) " >&6 3932 3934 else 3933 3935 lt_cv_nm_interface="BSD nm" 3934 3936 echo "int some_variable = 0;" > conftest.$ac_ext 3935 - (eval echo "\"\$as_me:3935: $ac_compile\"" >&5) 3937 + (eval echo "\"\$as_me:3937: $ac_compile\"" >&5) 3936 3938 (eval "$ac_compile" 2>conftest.err) 3937 3939 cat conftest.err >&5 3938 - (eval echo "\"\$as_me:3938: $NM \\\"conftest.$ac_objext\\\"\"" >&5) 3940 + (eval echo "\"\$as_me:3940: $NM \\\"conftest.$ac_objext\\\"\"" >&5) 3939 3941 (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) 3940 3942 cat conftest.err >&5 3941 - (eval echo "\"\$as_me:3941: output\"" >&5) 3943 + (eval echo "\"\$as_me:3943: output\"" >&5) 3942 3944 cat conftest.out >&5 3943 3945 if $GREP 'External.*some_variable' conftest.out > /dev/null; then 3944 3946 lt_cv_nm_interface="MS dumpbin" 3945 3947 fi 3946 3948 rm -f conftest* 3947 3949 fi 3948 3950 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 ................................................................................ 5140 5142 ;; 5141 5143 esac 5142 5144 fi 5143 5145 rm -rf conftest* 5144 5146 ;; 5145 5147 *-*-irix6*) 5146 5148 # Find out which ABI we are using. 5147 - echo '#line 5147 "configure"' > conftest.$ac_ext 5149 + echo '#line 5149 "configure"' > conftest.$ac_ext 5148 5150 if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 5149 5151 (eval $ac_compile) 2>&5 5150 5152 ac_status=$? 5151 5153 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 5152 5154 test $ac_status = 0; }; then 5153 5155 if test "$lt_cv_prog_gnu_ld" = yes; then 5154 5156 case `/usr/bin/file conftest.$ac_objext` in ................................................................................ 6665 6667 # Note that $ac_compile itself does not contain backslashes and begins 6666 6668 # with a dollar sign (not a hyphen), so the echo should work correctly. 6667 6669 # The option is referenced via a variable to avoid confusing sed. 6668 6670 lt_compile=`echo "$ac_compile" | $SED \ 6669 6671 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ 6670 6672 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ 6671 6673 -e 's:$: $lt_compiler_flag:'` 6672 - (eval echo "\"\$as_me:6672: $lt_compile\"" >&5) 6674 + (eval echo "\"\$as_me:6674: $lt_compile\"" >&5) 6673 6675 (eval "$lt_compile" 2>conftest.err) 6674 6676 ac_status=$? 6675 6677 cat conftest.err >&5 6676 - echo "$as_me:6676: \$? = $ac_status" >&5 6678 + echo "$as_me:6678: \$? = $ac_status" >&5 6677 6679 if (exit $ac_status) && test -s "$ac_outfile"; then 6678 6680 # The compiler can only warn and ignore the option if not recognized 6679 6681 # So say no if there are warnings other than the usual output. 6680 6682 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp 6681 6683 $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 6682 6684 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then 6683 6685 lt_cv_prog_compiler_rtti_exceptions=yes ................................................................................ 7004 7006 # Note that $ac_compile itself does not contain backslashes and begins 7005 7007 # with a dollar sign (not a hyphen), so the echo should work correctly. 7006 7008 # The option is referenced via a variable to avoid confusing sed. 7007 7009 lt_compile=`echo "$ac_compile" | $SED \ 7008 7010 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ 7009 7011 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ 7010 7012 -e 's:$: $lt_compiler_flag:'` 7011 - (eval echo "\"\$as_me:7011: $lt_compile\"" >&5) 7013 + (eval echo "\"\$as_me:7013: $lt_compile\"" >&5) 7012 7014 (eval "$lt_compile" 2>conftest.err) 7013 7015 ac_status=$? 7014 7016 cat conftest.err >&5 7015 - echo "$as_me:7015: \$? = $ac_status" >&5 7017 + echo "$as_me:7017: \$? = $ac_status" >&5 7016 7018 if (exit $ac_status) && test -s "$ac_outfile"; then 7017 7019 # The compiler can only warn and ignore the option if not recognized 7018 7020 # So say no if there are warnings other than the usual output. 7019 7021 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp 7020 7022 $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 7021 7023 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then 7022 7024 lt_cv_prog_compiler_pic_works=yes ................................................................................ 7109 7111 # (2) before a word containing "conftest.", or (3) at the end. 7110 7112 # Note that $ac_compile itself does not contain backslashes and begins 7111 7113 # with a dollar sign (not a hyphen), so the echo should work correctly. 7112 7114 lt_compile=`echo "$ac_compile" | $SED \ 7113 7115 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ 7114 7116 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ 7115 7117 -e 's:$: $lt_compiler_flag:'` 7116 - (eval echo "\"\$as_me:7116: $lt_compile\"" >&5) 7118 + (eval echo "\"\$as_me:7118: $lt_compile\"" >&5) 7117 7119 (eval "$lt_compile" 2>out/conftest.err) 7118 7120 ac_status=$? 7119 7121 cat out/conftest.err >&5 7120 - echo "$as_me:7120: \$? = $ac_status" >&5 7122 + echo "$as_me:7122: \$? = $ac_status" >&5 7121 7123 if (exit $ac_status) && test -s out/conftest2.$ac_objext 7122 7124 then 7123 7125 # The compiler can only warn and ignore the option if not recognized 7124 7126 # So say no if there are warnings 7125 7127 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp 7126 7128 $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 7127 7129 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then ................................................................................ 7164 7166 # (2) before a word containing "conftest.", or (3) at the end. 7165 7167 # Note that $ac_compile itself does not contain backslashes and begins 7166 7168 # with a dollar sign (not a hyphen), so the echo should work correctly. 7167 7169 lt_compile=`echo "$ac_compile" | $SED \ 7168 7170 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ 7169 7171 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ 7170 7172 -e 's:$: $lt_compiler_flag:'` 7171 - (eval echo "\"\$as_me:7171: $lt_compile\"" >&5) 7173 + (eval echo "\"\$as_me:7173: $lt_compile\"" >&5) 7172 7174 (eval "$lt_compile" 2>out/conftest.err) 7173 7175 ac_status=$? 7174 7176 cat out/conftest.err >&5 7175 - echo "$as_me:7175: \$? = $ac_status" >&5 7177 + echo "$as_me:7177: \$? = $ac_status" >&5 7176 7178 if (exit $ac_status) && test -s out/conftest2.$ac_objext 7177 7179 then 7178 7180 # The compiler can only warn and ignore the option if not recognized 7179 7181 # So say no if there are warnings 7180 7182 $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp 7181 7183 $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 7182 7184 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then ................................................................................ 9544 9546 else 9545 9547 if test "$cross_compiling" = yes; then : 9546 9548 lt_cv_dlopen_self=cross 9547 9549 else 9548 9550 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 9549 9551 lt_status=$lt_dlunknown 9550 9552 cat > conftest.$ac_ext <<_LT_EOF 9551 -#line 9551 "configure" 9553 +#line 9553 "configure" 9552 9554 #include "confdefs.h" 9553 9555 9554 9556 #if HAVE_DLFCN_H 9555 9557 #include <dlfcn.h> 9556 9558 #endif 9557 9559 9558 9560 #include <stdio.h> ................................................................................ 9640 9642 else 9641 9643 if test "$cross_compiling" = yes; then : 9642 9644 lt_cv_dlopen_self_static=cross 9643 9645 else 9644 9646 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 9645 9647 lt_status=$lt_dlunknown 9646 9648 cat > conftest.$ac_ext <<_LT_EOF 9647 -#line 9647 "configure" 9649 +#line 9649 "configure" 9648 9650 #include "confdefs.h" 9649 9651 9650 9652 #if HAVE_DLFCN_H 9651 9653 #include <dlfcn.h> 9652 9654 #endif 9653 9655 9654 9656 #include <stdio.h> ................................................................................ 11605 11607 if test "${enable_update_limit+set}" = set; then : 11606 11608 enableval=$enable_update_limit; 11607 11609 fi 11608 11610 11609 11611 if test "${enable_udlimit}" = "yes" ; then 11610 11612 OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" 11611 11613 fi 11614 + 11615 +######### 11616 +# See whether we should enable GEOPOLY 11617 +# Check whether --enable-geopoly was given. 11618 +if test "${enable_geopoly+set}" = set; then : 11619 + enableval=$enable_geopoly; enable_geopoly=yes 11620 +else 11621 + enable_geopoly=no 11622 +fi 11623 + 11624 +if test "${enable_geopoly}" = "yes" ; then 11625 + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY" 11626 + enable_rtree=yes 11627 +fi 11612 11628 11613 11629 ######### 11614 11630 # See whether we should enable RTREE 11615 11631 # Check whether --enable-rtree was given. 11616 11632 if test "${enable_rtree+set}" = set; then : 11617 11633 enableval=$enable_rtree; 11618 11634 fi
Changes to configure.ac.
644 644 # See whether we should enable the LIMIT clause on UPDATE and DELETE 645 645 # statements. 646 646 AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit], 647 647 [Enable the UPDATE/DELETE LIMIT clause])) 648 648 if test "${enable_udlimit}" = "yes" ; then 649 649 OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" 650 650 fi 651 + 652 +######### 653 +# See whether we should enable GEOPOLY 654 +AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly], 655 + [Enable the GEOPOLY extension]), 656 + [enable_geopoly=yes],[enable_geopoly=no]) 657 +if test "${enable_geopoly}" = "yes" ; then 658 + OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY" 659 + enable_rtree=yes 660 +fi 651 661 652 662 ######### 653 663 # See whether we should enable RTREE 654 664 AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree], 655 665 [Enable the RTREE extension])) 656 666 if test "${enable_rtree}" = "yes" ; then 657 667 OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
Changes to ext/misc/completion.c.
361 361 completionCursorReset(pCur); 362 362 if( idxNum & 1 ){ 363 363 pCur->nPrefix = sqlite3_value_bytes(argv[iArg]); 364 364 if( pCur->nPrefix>0 ){ 365 365 pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); 366 366 if( pCur->zPrefix==0 ) return SQLITE_NOMEM; 367 367 } 368 - iArg++; 368 + iArg = 1; 369 369 } 370 370 if( idxNum & 2 ){ 371 371 pCur->nLine = sqlite3_value_bytes(argv[iArg]); 372 372 if( pCur->nLine>0 ){ 373 373 pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg])); 374 374 if( pCur->zLine==0 ) return SQLITE_NOMEM; 375 375 } 376 - iArg++; 377 376 } 378 377 if( pCur->zLine!=0 && pCur->zPrefix==0 ){ 379 378 int i = pCur->nLine; 380 379 while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){ 381 380 i--; 382 381 } 383 382 pCur->nPrefix = pCur->nLine - i;
Changes to ext/misc/json1.c.
168 168 JsonNode *aNode; /* Array of nodes containing the parse */ 169 169 const char *zJson; /* Original JSON string */ 170 170 u32 *aUp; /* Index of parent of each node */ 171 171 u8 oom; /* Set to true if out of memory */ 172 172 u8 nErr; /* Number of errors seen */ 173 173 u16 iDepth; /* Nesting depth */ 174 174 int nJson; /* Length of the zJson string in bytes */ 175 + u32 iHold; /* Replace cache line with the lowest iHold value */ 175 176 }; 176 177 177 178 /* 178 179 ** Maximum nesting depth of JSON for this implementation. 179 180 ** 180 181 ** This limit is needed to avoid a stack overflow in the recursive 181 182 ** descent parser. A depth of 2000 is far deeper than any sane JSON ................................................................................ 972 973 jsonParseFillInParentage(pParse, 0, 0); 973 974 return SQLITE_OK; 974 975 } 975 976 976 977 /* 977 978 ** Magic number used for the JSON parse cache in sqlite3_get_auxdata() 978 979 */ 979 -#define JSON_CACHE_ID (-429938) 980 +#define JSON_CACHE_ID (-429938) /* First cache entry */ 981 +#define JSON_CACHE_SZ 4 /* Max number of cache entries */ 980 982 981 983 /* 982 984 ** Obtain a complete parse of the JSON found in the first argument 983 985 ** of the argv array. Use the sqlite3_get_auxdata() cache for this 984 986 ** parse if it is available. If the cache is not available or if it 985 987 ** is no longer valid, parse the JSON again and return the new parse, 986 988 ** and also register the new parse so that it will be available for 987 989 ** future sqlite3_get_auxdata() calls. 988 990 */ 989 991 static JsonParse *jsonParseCached( 990 992 sqlite3_context *pCtx, 991 - sqlite3_value **argv 993 + sqlite3_value **argv, 994 + sqlite3_context *pErrCtx 992 995 ){ 993 996 const char *zJson = (const char*)sqlite3_value_text(argv[0]); 994 997 int nJson = sqlite3_value_bytes(argv[0]); 995 998 JsonParse *p; 999 + JsonParse *pMatch = 0; 1000 + int iKey; 1001 + int iMinKey = 0; 1002 + u32 iMinHold = 0xffffffff; 1003 + u32 iMaxHold = 0; 996 1004 if( zJson==0 ) return 0; 997 - p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); 998 - if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){ 999 - p->nErr = 0; 1000 - return p; /* The cached entry matches, so return it */ 1005 + for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){ 1006 + p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey); 1007 + if( p==0 ){ 1008 + iMinKey = iKey; 1009 + break; 1010 + } 1011 + if( pMatch==0 1012 + && p->nJson==nJson 1013 + && memcmp(p->zJson,zJson,nJson)==0 1014 + ){ 1015 + p->nErr = 0; 1016 + pMatch = p; 1017 + }else if( p->iHold<iMinHold ){ 1018 + iMinHold = p->iHold; 1019 + iMinKey = iKey; 1020 + } 1021 + if( p->iHold>iMaxHold ){ 1022 + iMaxHold = p->iHold; 1023 + } 1024 + } 1025 + if( pMatch ){ 1026 + pMatch->nErr = 0; 1027 + pMatch->iHold = iMaxHold+1; 1028 + return pMatch; 1001 1029 } 1002 1030 p = sqlite3_malloc( sizeof(*p) + nJson + 1 ); 1003 1031 if( p==0 ){ 1004 1032 sqlite3_result_error_nomem(pCtx); 1005 1033 return 0; 1006 1034 } 1007 1035 memset(p, 0, sizeof(*p)); 1008 1036 p->zJson = (char*)&p[1]; 1009 1037 memcpy((char*)p->zJson, zJson, nJson+1); 1010 - if( jsonParse(p, pCtx, p->zJson) ){ 1038 + if( jsonParse(p, pErrCtx, p->zJson) ){ 1011 1039 sqlite3_free(p); 1012 1040 return 0; 1013 1041 } 1014 1042 p->nJson = nJson; 1015 - sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree); 1016 - return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID); 1043 + p->iHold = iMaxHold+1; 1044 + sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p, 1045 + (void(*)(void*))jsonParseFree); 1046 + return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey); 1017 1047 } 1018 1048 1019 1049 /* 1020 1050 ** Compare the OBJECT label at pNode against zKey,nKey. Return true on 1021 1051 ** a match. 1022 1052 */ 1023 1053 static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ ................................................................................ 1382 1412 sqlite3_value **argv 1383 1413 ){ 1384 1414 JsonParse *p; /* The parse */ 1385 1415 sqlite3_int64 n = 0; 1386 1416 u32 i; 1387 1417 JsonNode *pNode; 1388 1418 1389 - p = jsonParseCached(ctx, argv); 1419 + p = jsonParseCached(ctx, argv, ctx); 1390 1420 if( p==0 ) return; 1391 1421 assert( p->nNode ); 1392 1422 if( argc==2 ){ 1393 1423 const char *zPath = (const char*)sqlite3_value_text(argv[1]); 1394 1424 pNode = jsonLookup(p, zPath, 0, ctx); 1395 1425 }else{ 1396 1426 pNode = p->aNode; ................................................................................ 1423 1453 JsonParse *p; /* The parse */ 1424 1454 JsonNode *pNode; 1425 1455 const char *zPath; 1426 1456 JsonString jx; 1427 1457 int i; 1428 1458 1429 1459 if( argc<2 ) return; 1430 - p = jsonParseCached(ctx, argv); 1460 + p = jsonParseCached(ctx, argv, ctx); 1431 1461 if( p==0 ) return; 1432 1462 jsonInit(&jx, ctx); 1433 1463 jsonAppendChar(&jx, '['); 1434 1464 for(i=1; i<argc; i++){ 1435 1465 zPath = (const char*)sqlite3_value_text(argv[i]); 1436 1466 pNode = jsonLookup(p, zPath, 0, ctx); 1437 1467 if( p->nErr ) break; ................................................................................ 1730 1760 ** either the JSON or PATH inputs are not well-formed. 1731 1761 */ 1732 1762 static void jsonTypeFunc( 1733 1763 sqlite3_context *ctx, 1734 1764 int argc, 1735 1765 sqlite3_value **argv 1736 1766 ){ 1737 - JsonParse x; /* The parse */ 1767 + JsonParse *p; /* The parse */ 1738 1768 const char *zPath; 1739 1769 JsonNode *pNode; 1740 1770 1741 - if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; 1742 - assert( x.nNode ); 1771 + p = jsonParseCached(ctx, argv, ctx); 1772 + if( p==0 ) return; 1743 1773 if( argc==2 ){ 1744 1774 zPath = (const char*)sqlite3_value_text(argv[1]); 1745 - pNode = jsonLookup(&x, zPath, 0, ctx); 1775 + pNode = jsonLookup(p, zPath, 0, ctx); 1746 1776 }else{ 1747 - pNode = x.aNode; 1777 + pNode = p->aNode; 1748 1778 } 1749 1779 if( pNode ){ 1750 1780 sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); 1751 1781 } 1752 - jsonParseReset(&x); 1753 1782 } 1754 1783 1755 1784 /* 1756 1785 ** json_valid(JSON) 1757 1786 ** 1758 1787 ** Return 1 if JSON is a well-formed JSON string according to RFC-7159. 1759 1788 ** Return 0 otherwise. 1760 1789 */ 1761 1790 static void jsonValidFunc( 1762 1791 sqlite3_context *ctx, 1763 1792 int argc, 1764 1793 sqlite3_value **argv 1765 1794 ){ 1766 - JsonParse x; /* The parse */ 1767 - int rc = 0; 1768 - 1795 + JsonParse *p; /* The parse */ 1769 1796 UNUSED_PARAM(argc); 1770 - if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){ 1771 - rc = 1; 1772 - } 1773 - jsonParseReset(&x); 1774 - sqlite3_result_int(ctx, rc); 1797 + p = jsonParseCached(ctx, argv, 0); 1798 + sqlite3_result_int(ctx, p!=0); 1775 1799 } 1776 1800 1777 1801 1778 1802 /**************************************************************************** 1779 1803 ** Aggregate SQL function implementations 1780 1804 ****************************************************************************/ 1781 1805 /*
Added ext/rtree/geopoly.c.
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 +#ifndef JSON_NULL /* The following stuff repeats things found in json1 */ 30 +/* 31 +** Versions of isspace(), isalnum() and isdigit() to which it is safe 32 +** to pass signed char values. 33 +*/ 34 +#ifdef sqlite3Isdigit 35 + /* Use the SQLite core versions if this routine is part of the 36 + ** SQLite amalgamation */ 37 +# define safe_isdigit(x) sqlite3Isdigit(x) 38 +# define safe_isalnum(x) sqlite3Isalnum(x) 39 +# define safe_isxdigit(x) sqlite3Isxdigit(x) 40 +#else 41 + /* Use the standard library for separate compilation */ 42 +#include <ctype.h> /* amalgamator: keep */ 43 +# define safe_isdigit(x) isdigit((unsigned char)(x)) 44 +# define safe_isalnum(x) isalnum((unsigned char)(x)) 45 +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) 46 +#endif 47 + 48 +/* 49 +** Growing our own isspace() routine this way is twice as fast as 50 +** the library isspace() function. 51 +*/ 52 +static const char geopolyIsSpace[] = { 53 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 54 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55 + 1, 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 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69 +}; 70 +#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x]) 71 +#endif /* JSON NULL - back to original code */ 72 + 73 +/* Compiler and version */ 74 +#ifndef GCC_VERSION 75 +#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) 76 +# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) 77 +#else 78 +# define GCC_VERSION 0 79 +#endif 80 +#endif 81 +#ifndef MSVC_VERSION 82 +#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) 83 +# define MSVC_VERSION _MSC_VER 84 +#else 85 +# define MSVC_VERSION 0 86 +#endif 87 +#endif 88 + 89 +/* Datatype for coordinates 90 +*/ 91 +typedef float GeoCoord; 92 + 93 +/* 94 +** Internal representation of a polygon. 95 +** 96 +** The polygon consists of a sequence of vertexes. There is a line 97 +** segment between each pair of vertexes, and one final segment from 98 +** the last vertex back to the first. (This differs from the GeoJSON 99 +** standard in which the final vertex is a repeat of the first.) 100 +** 101 +** The polygon follows the right-hand rule. The area to the right of 102 +** each segment is "outside" and the area to the left is "inside". 103 +** 104 +** The on-disk representation consists of a 4-byte header followed by 105 +** the values. The 4-byte header is: 106 +** 107 +** encoding (1 byte) 0=big-endian, 1=little-endian 108 +** nvertex (3 bytes) Number of vertexes as a big-endian integer 109 +*/ 110 +typedef struct GeoPoly GeoPoly; 111 +struct GeoPoly { 112 + int nVertex; /* Number of vertexes */ 113 + unsigned char hdr[4]; /* Header for on-disk representation */ 114 + GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */ 115 +}; 116 + 117 +/* 118 +** State of a parse of a GeoJSON input. 119 +*/ 120 +typedef struct GeoParse GeoParse; 121 +struct GeoParse { 122 + const unsigned char *z; /* Unparsed input */ 123 + int nVertex; /* Number of vertexes in a[] */ 124 + int nAlloc; /* Space allocated to a[] */ 125 + int nErr; /* Number of errors encountered */ 126 + GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */ 127 +}; 128 + 129 +/* Do a 4-byte byte swap */ 130 +static void geopolySwab32(unsigned char *a){ 131 + unsigned char t = a[0]; 132 + a[0] = a[3]; 133 + a[3] = t; 134 + t = a[1]; 135 + a[1] = a[2]; 136 + a[2] = t; 137 +} 138 + 139 +/* Skip whitespace. Return the next non-whitespace character. */ 140 +static char geopolySkipSpace(GeoParse *p){ 141 + while( p->z[0] && safe_isspace(p->z[0]) ) p->z++; 142 + return p->z[0]; 143 +} 144 + 145 +/* Parse out a number. Write the value into *pVal if pVal!=0. 146 +** return non-zero on success and zero if the next token is not a number. 147 +*/ 148 +static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){ 149 + char c = geopolySkipSpace(p); 150 + const unsigned char *z = p->z; 151 + int j = 0; 152 + int seenDP = 0; 153 + int seenE = 0; 154 + if( c=='-' ){ 155 + j = 1; 156 + c = z[j]; 157 + } 158 + if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; 159 + for(;; j++){ 160 + c = z[j]; 161 + if( c>='0' && c<='9' ) continue; 162 + if( c=='.' ){ 163 + if( z[j-1]=='-' ) return 0; 164 + if( seenDP ) return 0; 165 + seenDP = 1; 166 + continue; 167 + } 168 + if( c=='e' || c=='E' ){ 169 + if( z[j-1]<'0' ) return 0; 170 + if( seenE ) return -1; 171 + seenDP = seenE = 1; 172 + c = z[j+1]; 173 + if( c=='+' || c=='-' ){ 174 + j++; 175 + c = z[j+1]; 176 + } 177 + if( c<'0' || c>'9' ) return 0; 178 + continue; 179 + } 180 + break; 181 + } 182 + if( z[j-1]<'0' ) return 0; 183 + if( pVal ) *pVal = atof((const char*)p->z); 184 + p->z += j; 185 + return 1; 186 +} 187 + 188 +/* 189 +** If the input is a well-formed JSON array of coordinates with at least 190 +** four coordinates and where each coordinate is itself a two-value array, 191 +** then convert the JSON into a GeoPoly object and return a pointer to 192 +** that object. 193 +** 194 +** If any error occurs, return NULL. 195 +*/ 196 +static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ 197 + GeoParse s; 198 + int rc = SQLITE_OK; 199 + memset(&s, 0, sizeof(s)); 200 + s.z = z; 201 + if( geopolySkipSpace(&s)=='[' ){ 202 + s.z++; 203 + while( geopolySkipSpace(&s)=='[' ){ 204 + int ii = 0; 205 + char c; 206 + s.z++; 207 + if( s.nVertex<=s.nAlloc ){ 208 + GeoCoord *aNew; 209 + s.nAlloc = s.nAlloc*2 + 16; 210 + aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 ); 211 + if( aNew==0 ){ 212 + rc = SQLITE_NOMEM; 213 + s.nErr++; 214 + break; 215 + } 216 + s.a = aNew; 217 + } 218 + while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){ 219 + ii++; 220 + if( ii==2 ) s.nVertex++; 221 + c = geopolySkipSpace(&s); 222 + s.z++; 223 + if( c==',' ) continue; 224 + if( c==']' && ii>=2 ) break; 225 + s.nErr++; 226 + rc = SQLITE_ERROR; 227 + goto parse_json_err; 228 + } 229 + if( geopolySkipSpace(&s)==',' ){ 230 + s.z++; 231 + continue; 232 + } 233 + break; 234 + } 235 + if( geopolySkipSpace(&s)==']' 236 + && s.nVertex>=4 237 + && s.a[0]==s.a[s.nVertex*2-2] 238 + && s.a[1]==s.a[s.nVertex*2-1] 239 + && (s.z++, geopolySkipSpace(&s)==0) 240 + ){ 241 + int nByte; 242 + GeoPoly *pOut; 243 + int x = 1; 244 + s.nVertex--; /* Remove the redundant vertex at the end */ 245 + nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord); 246 + pOut = sqlite3_malloc64( nByte ); 247 + x = 1; 248 + if( pOut==0 ) goto parse_json_err; 249 + pOut->nVertex = s.nVertex; 250 + memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord)); 251 + pOut->hdr[0] = *(unsigned char*)&x; 252 + pOut->hdr[1] = (s.nVertex>>16)&0xff; 253 + pOut->hdr[2] = (s.nVertex>>8)&0xff; 254 + pOut->hdr[3] = s.nVertex&0xff; 255 + sqlite3_free(s.a); 256 + if( pRc ) *pRc = SQLITE_OK; 257 + return pOut; 258 + }else{ 259 + s.nErr++; 260 + rc = SQLITE_ERROR; 261 + } 262 + } 263 +parse_json_err: 264 + if( pRc ) *pRc = rc; 265 + sqlite3_free(s.a); 266 + return 0; 267 +} 268 + 269 +/* 270 +** Given a function parameter, try to interpret it as a polygon, either 271 +** in the binary format or JSON text. Compute a GeoPoly object and 272 +** return a pointer to that object. Or if the input is not a well-formed 273 +** polygon, put an error message in sqlite3_context and return NULL. 274 +*/ 275 +static GeoPoly *geopolyFuncParam( 276 + sqlite3_context *pCtx, /* Context for error messages */ 277 + sqlite3_value *pVal, /* The value to decode */ 278 + int *pRc /* Write error here */ 279 +){ 280 + GeoPoly *p = 0; 281 + int nByte; 282 + if( sqlite3_value_type(pVal)==SQLITE_BLOB 283 + && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord)) 284 + ){ 285 + const unsigned char *a = sqlite3_value_blob(pVal); 286 + int nVertex; 287 + nVertex = (a[1]<<16) + (a[2]<<8) + a[3]; 288 + if( (a[0]==0 || a[0]==1) 289 + && (nVertex*2*sizeof(GeoCoord) + 4)==nByte 290 + ){ 291 + p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) ); 292 + if( p==0 ){ 293 + if( pRc ) *pRc = SQLITE_NOMEM; 294 + if( pCtx ) sqlite3_result_error_nomem(pCtx); 295 + }else{ 296 + int x = 1; 297 + p->nVertex = nVertex; 298 + memcpy(p->hdr, a, nByte); 299 + if( a[0] != *(unsigned char*)&x ){ 300 + int ii; 301 + for(ii=0; ii<nVertex*2; ii++){ 302 + geopolySwab32((unsigned char*)&p->a[ii]); 303 + } 304 + p->hdr[0] ^= 1; 305 + } 306 + } 307 + } 308 + if( pRc ) *pRc = SQLITE_OK; 309 + return p; 310 + }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){ 311 + const unsigned char *zJson = sqlite3_value_text(pVal); 312 + if( zJson==0 ){ 313 + if( pRc ) *pRc = SQLITE_NOMEM; 314 + return 0; 315 + } 316 + return geopolyParseJson(zJson, pRc); 317 + }else{ 318 + if( pRc ) *pRc = SQLITE_ERROR; 319 + return 0; 320 + } 321 +} 322 + 323 +/* 324 +** Implementation of the geopoly_blob(X) function. 325 +** 326 +** If the input is a well-formed Geopoly BLOB or JSON string 327 +** then return the BLOB representation of the polygon. Otherwise 328 +** return NULL. 329 +*/ 330 +static void geopolyBlobFunc( 331 + sqlite3_context *context, 332 + int argc, 333 + sqlite3_value **argv 334 +){ 335 + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 336 + if( p ){ 337 + sqlite3_result_blob(context, p->hdr, 338 + 4+8*p->nVertex, SQLITE_TRANSIENT); 339 + sqlite3_free(p); 340 + } 341 +} 342 + 343 +/* 344 +** SQL function: geopoly_json(X) 345 +** 346 +** Interpret X as a polygon and render it as a JSON array 347 +** of coordinates. Or, if X is not a valid polygon, return NULL. 348 +*/ 349 +static void geopolyJsonFunc( 350 + sqlite3_context *context, 351 + int argc, 352 + sqlite3_value **argv 353 +){ 354 + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 355 + if( p ){ 356 + sqlite3 *db = sqlite3_context_db_handle(context); 357 + sqlite3_str *x = sqlite3_str_new(db); 358 + int i; 359 + sqlite3_str_append(x, "[", 1); 360 + for(i=0; i<p->nVertex; i++){ 361 + sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]); 362 + } 363 + sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]); 364 + sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); 365 + sqlite3_free(p); 366 + } 367 +} 368 + 369 +/* 370 +** SQL function: geopoly_svg(X, ....) 371 +** 372 +** Interpret X as a polygon and render it as a SVG <polyline>. 373 +** Additional arguments are added as attributes to the <polyline>. 374 +*/ 375 +static void geopolySvgFunc( 376 + sqlite3_context *context, 377 + int argc, 378 + sqlite3_value **argv 379 +){ 380 + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 381 + if( p ){ 382 + sqlite3 *db = sqlite3_context_db_handle(context); 383 + sqlite3_str *x = sqlite3_str_new(db); 384 + int i; 385 + char cSep = '\''; 386 + sqlite3_str_appendf(x, "<polyline points="); 387 + for(i=0; i<p->nVertex; i++){ 388 + sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]); 389 + cSep = ' '; 390 + } 391 + sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]); 392 + for(i=1; i<argc; i++){ 393 + const char *z = (const char*)sqlite3_value_text(argv[i]); 394 + if( z && z[0] ){ 395 + sqlite3_str_appendf(x, " %s", z); 396 + } 397 + } 398 + sqlite3_str_appendf(x, "></polyline>"); 399 + sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free); 400 + sqlite3_free(p); 401 + } 402 +} 403 + 404 +/* 405 +** SQL Function: geopoly_xform(poly, A, B, C, D, E, F) 406 +** 407 +** Transform and/or translate a polygon as follows: 408 +** 409 +** x1 = A*x0 + B*y0 + E 410 +** y1 = C*x0 + D*y0 + F 411 +** 412 +** For a translation: 413 +** 414 +** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset) 415 +** 416 +** Rotate by R around the point (0,0): 417 +** 418 +** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0) 419 +*/ 420 +static void geopolyXformFunc( 421 + sqlite3_context *context, 422 + int argc, 423 + sqlite3_value **argv 424 +){ 425 + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 426 + double A = sqlite3_value_double(argv[1]); 427 + double B = sqlite3_value_double(argv[2]); 428 + double C = sqlite3_value_double(argv[3]); 429 + double D = sqlite3_value_double(argv[4]); 430 + double E = sqlite3_value_double(argv[5]); 431 + double F = sqlite3_value_double(argv[6]); 432 + GeoCoord x1, y1, x0, y0; 433 + int ii; 434 + if( p ){ 435 + for(ii=0; ii<p->nVertex; ii++){ 436 + x0 = p->a[ii*2]; 437 + y0 = p->a[ii*2+1]; 438 + x1 = A*x0 + B*y0 + E; 439 + y1 = C*x0 + D*y0 + F; 440 + p->a[ii*2] = x1; 441 + p->a[ii*2+1] = y1; 442 + } 443 + sqlite3_result_blob(context, p->hdr, 444 + 4+8*p->nVertex, SQLITE_TRANSIENT); 445 + sqlite3_free(p); 446 + } 447 +} 448 + 449 +/* 450 +** Implementation of the geopoly_area(X) function. 451 +** 452 +** If the input is a well-formed Geopoly BLOB then return the area 453 +** enclosed by the polygon. If the polygon circulates clockwise instead 454 +** of counterclockwise (as it should) then return the negative of the 455 +** enclosed area. Otherwise return NULL. 456 +*/ 457 +static void geopolyAreaFunc( 458 + sqlite3_context *context, 459 + int argc, 460 + sqlite3_value **argv 461 +){ 462 + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); 463 + if( p ){ 464 + double rArea = 0.0; 465 + int ii; 466 + for(ii=0; ii<p->nVertex-1; ii++){ 467 + rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ 468 + * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ 469 + * 0.5; 470 + } 471 + rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ 472 + * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ 473 + * 0.5; 474 + sqlite3_result_double(context, rArea); 475 + sqlite3_free(p); 476 + } 477 +} 478 + 479 +/* 480 +** If pPoly is a polygon, compute its bounding box. Then: 481 +** 482 +** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL 483 +** (2) otherwise, compute a GeoPoly for the bounding box and return the 484 +** new GeoPoly 485 +** 486 +** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from 487 +** the bounding box in aCoord and return a pointer to that GeoPoly. 488 +*/ 489 +static GeoPoly *geopolyBBox( 490 + sqlite3_context *context, /* For recording the error */ 491 + sqlite3_value *pPoly, /* The polygon */ 492 + RtreeCoord *aCoord, /* Results here */ 493 + int *pRc /* Error code here */ 494 +){ 495 + GeoPoly *pOut = 0; 496 + GeoPoly *p; 497 + float mnX, mxX, mnY, mxY; 498 + if( pPoly==0 && aCoord!=0 ){ 499 + p = 0; 500 + mnX = aCoord[0].f; 501 + mxX = aCoord[1].f; 502 + mnY = aCoord[2].f; 503 + mxY = aCoord[3].f; 504 + goto geopolyBboxFill; 505 + }else{ 506 + p = geopolyFuncParam(context, pPoly, pRc); 507 + } 508 + if( p ){ 509 + int ii; 510 + mnX = mxX = p->a[0]; 511 + mnY = mxY = p->a[1]; 512 + for(ii=1; ii<p->nVertex; ii++){ 513 + double r = p->a[ii*2]; 514 + if( r<mnX ) mnX = r; 515 + else if( r>mxX ) mxX = r; 516 + r = p->a[ii*2+1]; 517 + if( r<mnY ) mnY = r; 518 + else if( r>mxY ) mxY = r; 519 + } 520 + if( pRc ) *pRc = SQLITE_OK; 521 + if( aCoord==0 ){ 522 + geopolyBboxFill: 523 + pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); 524 + if( pOut==0 ){ 525 + sqlite3_free(p); 526 + if( context ) sqlite3_result_error_nomem(context); 527 + if( pRc ) *pRc = SQLITE_NOMEM; 528 + return 0; 529 + } 530 + pOut->nVertex = 4; 531 + ii = 1; 532 + pOut->hdr[0] = *(unsigned char*)ⅈ 533 + pOut->hdr[1] = 0; 534 + pOut->hdr[2] = 0; 535 + pOut->hdr[3] = 4; 536 + pOut->a[0] = mnX; 537 + pOut->a[1] = mnY; 538 + pOut->a[2] = mxX; 539 + pOut->a[3] = mnY; 540 + pOut->a[4] = mxX; 541 + pOut->a[5] = mxY; 542 + pOut->a[6] = mnX; 543 + pOut->a[7] = mxY; 544 + }else{ 545 + sqlite3_free(p); 546 + aCoord[0].f = mnX; 547 + aCoord[1].f = mxX; 548 + aCoord[2].f = mnY; 549 + aCoord[3].f = mxY; 550 + } 551 + } 552 + return pOut; 553 +} 554 + 555 +/* 556 +** Implementation of the geopoly_bbox(X) SQL function. 557 +*/ 558 +static void geopolyBBoxFunc( 559 + sqlite3_context *context, 560 + int argc, 561 + sqlite3_value **argv 562 +){ 563 + GeoPoly *p = geopolyBBox(context, argv[0], 0, 0); 564 + if( p ){ 565 + sqlite3_result_blob(context, p->hdr, 566 + 4+8*p->nVertex, SQLITE_TRANSIENT); 567 + sqlite3_free(p); 568 + } 569 +} 570 + 571 +/* 572 +** State vector for the geopoly_group_bbox() aggregate function. 573 +*/ 574 +typedef struct GeoBBox GeoBBox; 575 +struct GeoBBox { 576 + int isInit; 577 + RtreeCoord a[4]; 578 +}; 579 + 580 + 581 +/* 582 +** Implementation of the geopoly_group_bbox(X) aggregate SQL function. 583 +*/ 584 +static void geopolyBBoxStep( 585 + sqlite3_context *context, 586 + int argc, 587 + sqlite3_value **argv 588 +){ 589 + RtreeCoord a[4]; 590 + int rc = SQLITE_OK; 591 + (void)geopolyBBox(context, argv[0], a, &rc); 592 + if( rc==SQLITE_OK ){ 593 + GeoBBox *pBBox; 594 + pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox)); 595 + if( pBBox==0 ) return; 596 + if( pBBox->isInit==0 ){ 597 + pBBox->isInit = 1; 598 + memcpy(pBBox->a, a, sizeof(RtreeCoord)*4); 599 + }else{ 600 + if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0]; 601 + if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1]; 602 + if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2]; 603 + if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3]; 604 + } 605 + } 606 +} 607 +static void geopolyBBoxFinal( 608 + sqlite3_context *context 609 +){ 610 + GeoPoly *p; 611 + GeoBBox *pBBox; 612 + pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0); 613 + if( pBBox==0 ) return; 614 + p = geopolyBBox(context, 0, pBBox->a, 0); 615 + if( p ){ 616 + sqlite3_result_blob(context, p->hdr, 617 + 4+8*p->nVertex, SQLITE_TRANSIENT); 618 + sqlite3_free(p); 619 + } 620 +} 621 + 622 + 623 +/* 624 +** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2). 625 +** Returns: 626 +** 627 +** +2 x0,y0 is on the line segement 628 +** 629 +** +1 x0,y0 is beneath line segment 630 +** 631 +** 0 x0,y0 is not on or beneath the line segment or the line segment 632 +** is vertical and x0,y0 is not on the line segment 633 +** 634 +** The left-most coordinate min(x1,x2) is not considered to be part of 635 +** the line segment for the purposes of this analysis. 636 +*/ 637 +static int pointBeneathLine( 638 + double x0, double y0, 639 + double x1, double y1, 640 + double x2, double y2 641 +){ 642 + double y; 643 + if( x0==x1 && y0==y1 ) return 2; 644 + if( x1<x2 ){ 645 + if( x0<=x1 || x0>x2 ) return 0; 646 + }else if( x1>x2 ){ 647 + if( x0<=x2 || x0>x1 ) return 0; 648 + }else{ 649 + /* Vertical line segment */ 650 + if( x0!=x1 ) return 0; 651 + if( y0<y1 && y0<y2 ) return 0; 652 + if( y0>y1 && y0>y2 ) return 0; 653 + return 2; 654 + } 655 + y = y1 + (y2-y1)*(x0-x1)/(x2-x1); 656 + if( y0==y ) return 2; 657 + if( y0<y ) return 1; 658 + return 0; 659 +} 660 + 661 +/* 662 +** SQL function: geopoly_contains_point(P,X,Y) 663 +** 664 +** Return +2 if point X,Y is within polygon P. 665 +** Return +1 if point X,Y is on the polygon boundary. 666 +** Return 0 if point X,Y is outside the polygon 667 +*/ 668 +static void geopolyContainsPointFunc( 669 + sqlite3_context *context, 670 + int argc, 671 + sqlite3_value **argv 672 +){ 673 + GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 674 + double x0 = sqlite3_value_double(argv[1]); 675 + double y0 = sqlite3_value_double(argv[2]); 676 + int v = 0; 677 + int cnt = 0; 678 + int ii; 679 + if( p1==0 ) return; 680 + for(ii=0; ii<p1->nVertex-1; ii++){ 681 + v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], 682 + p1->a[ii*2+2],p1->a[ii*2+3]); 683 + if( v==2 ) break; 684 + cnt += v; 685 + } 686 + if( v!=2 ){ 687 + v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1], 688 + p1->a[0],p1->a[1]); 689 + } 690 + if( v==2 ){ 691 + sqlite3_result_int(context, 1); 692 + }else if( ((v+cnt)&1)==0 ){ 693 + sqlite3_result_int(context, 0); 694 + }else{ 695 + sqlite3_result_int(context, 2); 696 + } 697 + sqlite3_free(p1); 698 +} 699 + 700 +/* Forward declaration */ 701 +static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2); 702 + 703 +/* 704 +** SQL function: geopoly_within(P1,P2) 705 +** 706 +** Return +2 if P1 and P2 are the same polygon 707 +** Return +1 if P2 is contained within P1 708 +** Return 0 if any part of P2 is on the outside of P1 709 +** 710 +*/ 711 +static void geopolyWithinFunc( 712 + sqlite3_context *context, 713 + int argc, 714 + sqlite3_value **argv 715 +){ 716 + GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 717 + GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); 718 + if( p1 && p2 ){ 719 + int x = geopolyOverlap(p1, p2); 720 + if( x<0 ){ 721 + sqlite3_result_error_nomem(context); 722 + }else{ 723 + sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0); 724 + } 725 + } 726 + sqlite3_free(p1); 727 + sqlite3_free(p2); 728 +} 729 + 730 +/* Objects used by the overlap algorihm. */ 731 +typedef struct GeoEvent GeoEvent; 732 +typedef struct GeoSegment GeoSegment; 733 +typedef struct GeoOverlap GeoOverlap; 734 +struct GeoEvent { 735 + double x; /* X coordinate at which event occurs */ 736 + int eType; /* 0 for ADD, 1 for REMOVE */ 737 + GeoSegment *pSeg; /* The segment to be added or removed */ 738 + GeoEvent *pNext; /* Next event in the sorted list */ 739 +}; 740 +struct GeoSegment { 741 + double C, B; /* y = C*x + B */ 742 + double y; /* Current y value */ 743 + float y0; /* Initial y value */ 744 + unsigned char side; /* 1 for p1, 2 for p2 */ 745 + unsigned int idx; /* Which segment within the side */ 746 + GeoSegment *pNext; /* Next segment in a list sorted by y */ 747 +}; 748 +struct GeoOverlap { 749 + GeoEvent *aEvent; /* Array of all events */ 750 + GeoSegment *aSegment; /* Array of all segments */ 751 + int nEvent; /* Number of events */ 752 + int nSegment; /* Number of segments */ 753 +}; 754 + 755 +/* 756 +** Add a single segment and its associated events. 757 +*/ 758 +static void geopolyAddOneSegment( 759 + GeoOverlap *p, 760 + GeoCoord x0, 761 + GeoCoord y0, 762 + GeoCoord x1, 763 + GeoCoord y1, 764 + unsigned char side, 765 + unsigned int idx 766 +){ 767 + GeoSegment *pSeg; 768 + GeoEvent *pEvent; 769 + if( x0==x1 ) return; /* Ignore vertical segments */ 770 + if( x0>x1 ){ 771 + GeoCoord t = x0; 772 + x0 = x1; 773 + x1 = t; 774 + t = y0; 775 + y0 = y1; 776 + y1 = t; 777 + } 778 + pSeg = p->aSegment + p->nSegment; 779 + p->nSegment++; 780 + pSeg->C = (y1-y0)/(x1-x0); 781 + pSeg->B = y1 - x1*pSeg->C; 782 + pSeg->y0 = y0; 783 + pSeg->side = side; 784 + pSeg->idx = idx; 785 + pEvent = p->aEvent + p->nEvent; 786 + p->nEvent++; 787 + pEvent->x = x0; 788 + pEvent->eType = 0; 789 + pEvent->pSeg = pSeg; 790 + pEvent = p->aEvent + p->nEvent; 791 + p->nEvent++; 792 + pEvent->x = x1; 793 + pEvent->eType = 1; 794 + pEvent->pSeg = pSeg; 795 +} 796 + 797 + 798 + 799 +/* 800 +** Insert all segments and events for polygon pPoly. 801 +*/ 802 +static void geopolyAddSegments( 803 + GeoOverlap *p, /* Add segments to this Overlap object */ 804 + GeoPoly *pPoly, /* Take all segments from this polygon */ 805 + unsigned char side /* The side of pPoly */ 806 +){ 807 + unsigned int i; 808 + GeoCoord *x; 809 + for(i=0; i<(unsigned)pPoly->nVertex-1; i++){ 810 + x = pPoly->a + (i*2); 811 + geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i); 812 + } 813 + x = pPoly->a + (i*2); 814 + geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i); 815 +} 816 + 817 +/* 818 +** Merge two lists of sorted events by X coordinate 819 +*/ 820 +static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){ 821 + GeoEvent head, *pLast; 822 + head.pNext = 0; 823 + pLast = &head; 824 + while( pRight && pLeft ){ 825 + if( pRight->x <= pLeft->x ){ 826 + pLast->pNext = pRight; 827 + pLast = pRight; 828 + pRight = pRight->pNext; 829 + }else{ 830 + pLast->pNext = pLeft; 831 + pLast = pLeft; 832 + pLeft = pLeft->pNext; 833 + } 834 + } 835 + pLast->pNext = pRight ? pRight : pLeft; 836 + return head.pNext; 837 +} 838 + 839 +/* 840 +** Sort an array of nEvent event objects into a list. 841 +*/ 842 +static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){ 843 + int mx = 0; 844 + int i, j; 845 + GeoEvent *p; 846 + GeoEvent *a[50]; 847 + for(i=0; i<nEvent; i++){ 848 + p = &aEvent[i]; 849 + p->pNext = 0; 850 + for(j=0; j<mx && a[j]; j++){ 851 + p = geopolyEventMerge(a[j], p); 852 + a[j] = 0; 853 + } 854 + a[j] = p; 855 + if( j>=mx ) mx = j+1; 856 + } 857 + p = 0; 858 + for(i=0; i<mx; i++){ 859 + p = geopolyEventMerge(a[i], p); 860 + } 861 + return p; 862 +} 863 + 864 +/* 865 +** Merge two lists of sorted segments by Y, and then by C. 866 +*/ 867 +static GeoSegment *geopolySegmentMerge(GeoSegment *pLeft, GeoSegment *pRight){ 868 + GeoSegment head, *pLast; 869 + head.pNext = 0; 870 + pLast = &head; 871 + while( pRight && pLeft ){ 872 + double r = pRight->y - pLeft->y; 873 + if( r==0.0 ) r = pRight->C - pLeft->C; 874 + if( r<0.0 ){ 875 + pLast->pNext = pRight; 876 + pLast = pRight; 877 + pRight = pRight->pNext; 878 + }else{ 879 + pLast->pNext = pLeft; 880 + pLast = pLeft; 881 + pLeft = pLeft->pNext; 882 + } 883 + } 884 + pLast->pNext = pRight ? pRight : pLeft; 885 + return head.pNext; 886 +} 887 + 888 +/* 889 +** Sort a list of GeoSegments in order of increasing Y and in the event of 890 +** a tie, increasing C (slope). 891 +*/ 892 +static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ 893 + int mx = 0; 894 + int i; 895 + GeoSegment *p; 896 + GeoSegment *a[50]; 897 + while( pList ){ 898 + p = pList; 899 + pList = pList->pNext; 900 + p->pNext = 0; 901 + for(i=0; i<mx && a[i]; i++){ 902 + p = geopolySegmentMerge(a[i], p); 903 + a[i] = 0; 904 + } 905 + a[i] = p; 906 + if( i>=mx ) mx = i+1; 907 + } 908 + p = 0; 909 + for(i=0; i<mx; i++){ 910 + p = geopolySegmentMerge(a[i], p); 911 + } 912 + return p; 913 +} 914 + 915 +/* 916 +** Determine the overlap between two polygons 917 +*/ 918 +static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ 919 + int nVertex = p1->nVertex + p2->nVertex + 2; 920 + GeoOverlap *p; 921 + int nByte; 922 + GeoEvent *pThisEvent; 923 + double rX; 924 + int rc = 0; 925 + int needSort = 0; 926 + GeoSegment *pActive = 0; 927 + GeoSegment *pSeg; 928 + unsigned char aOverlap[4]; 929 + 930 + nByte = sizeof(GeoEvent)*nVertex*2 931 + + sizeof(GeoSegment)*nVertex 932 + + sizeof(GeoOverlap); 933 + p = sqlite3_malloc( nByte ); 934 + if( p==0 ) return -1; 935 + p->aEvent = (GeoEvent*)&p[1]; 936 + p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; 937 + p->nEvent = p->nSegment = 0; 938 + geopolyAddSegments(p, p1, 1); 939 + geopolyAddSegments(p, p2, 2); 940 + pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent); 941 + rX = pThisEvent->x==0.0 ? -1.0 : 0.0; 942 + memset(aOverlap, 0, sizeof(aOverlap)); 943 + while( pThisEvent ){ 944 + if( pThisEvent->x!=rX ){ 945 + GeoSegment *pPrev = 0; 946 + int iMask = 0; 947 + GEODEBUG(("Distinct X: %g\n", pThisEvent->x)); 948 + rX = pThisEvent->x; 949 + if( needSort ){ 950 + GEODEBUG(("SORT\n")); 951 + pActive = geopolySortSegmentsByYAndC(pActive); 952 + needSort = 0; 953 + } 954 + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 955 + if( pPrev ){ 956 + if( pPrev->y!=pSeg->y ){ 957 + GEODEBUG(("MASK: %d\n", iMask)); 958 + aOverlap[iMask] = 1; 959 + } 960 + } 961 + iMask ^= pSeg->side; 962 + pPrev = pSeg; 963 + } 964 + pPrev = 0; 965 + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 966 + double y = pSeg->C*rX + pSeg->B; 967 + GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y)); 968 + pSeg->y = y; 969 + if( pPrev ){ 970 + if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){ 971 + rc = 1; 972 + GEODEBUG(("Crossing: %d.%d and %d.%d\n", 973 + pPrev->side, pPrev->idx, 974 + pSeg->side, pSeg->idx)); 975 + goto geopolyOverlapDone; 976 + }else if( pPrev->y!=pSeg->y ){ 977 + GEODEBUG(("MASK: %d\n", iMask)); 978 + aOverlap[iMask] = 1; 979 + } 980 + } 981 + iMask ^= pSeg->side; 982 + pPrev = pSeg; 983 + } 984 + } 985 + GEODEBUG(("%s %d.%d C=%g B=%g\n", 986 + pThisEvent->eType ? "RM " : "ADD", 987 + pThisEvent->pSeg->side, pThisEvent->pSeg->idx, 988 + pThisEvent->pSeg->C, 989 + pThisEvent->pSeg->B)); 990 + if( pThisEvent->eType==0 ){ 991 + /* Add a segment */ 992 + pSeg = pThisEvent->pSeg; 993 + pSeg->y = pSeg->y0; 994 + pSeg->pNext = pActive; 995 + pActive = pSeg; 996 + needSort = 1; 997 + }else{ 998 + /* Remove a segment */ 999 + if( pActive==pThisEvent->pSeg ){ 1000 + pActive = pActive->pNext; 1001 + }else{ 1002 + for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){ 1003 + if( pSeg->pNext==pThisEvent->pSeg ){ 1004 + pSeg->pNext = pSeg->pNext->pNext; 1005 + break; 1006 + } 1007 + } 1008 + } 1009 + } 1010 + pThisEvent = pThisEvent->pNext; 1011 + } 1012 + if( aOverlap[3]==0 ){ 1013 + rc = 0; 1014 + }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){ 1015 + rc = 3; 1016 + }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){ 1017 + rc = 2; 1018 + }else if( aOverlap[1]==0 && aOverlap[2]==0 ){ 1019 + rc = 4; 1020 + }else{ 1021 + rc = 1; 1022 + } 1023 + 1024 +geopolyOverlapDone: 1025 + sqlite3_free(p); 1026 + return rc; 1027 +} 1028 + 1029 +/* 1030 +** SQL function: geopoly_overlap(P1,P2) 1031 +** 1032 +** Determine whether or not P1 and P2 overlap. Return value: 1033 +** 1034 +** 0 The two polygons are disjoint 1035 +** 1 They overlap 1036 +** 2 P1 is completely contained within P2 1037 +** 3 P2 is completely contained within P1 1038 +** 4 P1 and P2 are the same polygon 1039 +** NULL Either P1 or P2 or both are not valid polygons 1040 +*/ 1041 +static void geopolyOverlapFunc( 1042 + sqlite3_context *context, 1043 + int argc, 1044 + sqlite3_value **argv 1045 +){ 1046 + GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0); 1047 + GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0); 1048 + if( p1 && p2 ){ 1049 + int x = geopolyOverlap(p1, p2); 1050 + if( x<0 ){ 1051 + sqlite3_result_error_nomem(context); 1052 + }else{ 1053 + sqlite3_result_int(context, x); 1054 + } 1055 + } 1056 + sqlite3_free(p1); 1057 + sqlite3_free(p2); 1058 +} 1059 + 1060 +/* 1061 +** Enable or disable debugging output 1062 +*/ 1063 +static void geopolyDebugFunc( 1064 + sqlite3_context *context, 1065 + int argc, 1066 + sqlite3_value **argv 1067 +){ 1068 +#ifdef GEOPOLY_ENABLE_DEBUG 1069 + geo_debug = sqlite3_value_int(argv[0]); 1070 +#endif 1071 +} 1072 + 1073 +/* 1074 +** This function is the implementation of both the xConnect and xCreate 1075 +** methods of the geopoly virtual table. 1076 +** 1077 +** argv[0] -> module name 1078 +** argv[1] -> database name 1079 +** argv[2] -> table name 1080 +** argv[...] -> column names... 1081 +*/ 1082 +static int geopolyInit( 1083 + sqlite3 *db, /* Database connection */ 1084 + void *pAux, /* One of the RTREE_COORD_* constants */ 1085 + int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */ 1086 + sqlite3_vtab **ppVtab, /* OUT: New virtual table */ 1087 + char **pzErr, /* OUT: Error message, if any */ 1088 + int isCreate /* True for xCreate, false for xConnect */ 1089 +){ 1090 + int rc = SQLITE_OK; 1091 + Rtree *pRtree; 1092 + int nDb; /* Length of string argv[1] */ 1093 + int nName; /* Length of string argv[2] */ 1094 + sqlite3_str *pSql; 1095 + char *zSql; 1096 + int ii; 1097 + 1098 + sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); 1099 + 1100 + /* Allocate the sqlite3_vtab structure */ 1101 + nDb = (int)strlen(argv[1]); 1102 + nName = (int)strlen(argv[2]); 1103 + pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); 1104 + if( !pRtree ){ 1105 + return SQLITE_NOMEM; 1106 + } 1107 + memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2); 1108 + pRtree->nBusy = 1; 1109 + pRtree->base.pModule = &rtreeModule; 1110 + pRtree->zDb = (char *)&pRtree[1]; 1111 + pRtree->zName = &pRtree->zDb[nDb+1]; 1112 + pRtree->eCoordType = RTREE_COORD_REAL32; 1113 + pRtree->nDim = 2; 1114 + pRtree->nDim2 = 4; 1115 + memcpy(pRtree->zDb, argv[1], nDb); 1116 + memcpy(pRtree->zName, argv[2], nName); 1117 + 1118 + 1119 + /* Create/Connect to the underlying relational database schema. If 1120 + ** that is successful, call sqlite3_declare_vtab() to configure 1121 + ** the r-tree table schema. 1122 + */ 1123 + pSql = sqlite3_str_new(db); 1124 + sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape"); 1125 + pRtree->nAux = 1; /* Add one for _shape */ 1126 + pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */ 1127 + for(ii=3; ii<argc; ii++){ 1128 + pRtree->nAux++; 1129 + sqlite3_str_appendf(pSql, ",%s", argv[ii]); 1130 + } 1131 + sqlite3_str_appendf(pSql, ");"); 1132 + zSql = sqlite3_str_finish(pSql); 1133 + if( !zSql ){ 1134 + rc = SQLITE_NOMEM; 1135 + }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){ 1136 + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 1137 + } 1138 + sqlite3_free(zSql); 1139 + if( rc ) goto geopolyInit_fail; 1140 + pRtree->nBytesPerCell = 8 + pRtree->nDim2*4; 1141 + 1142 + /* Figure out the node size to use. */ 1143 + rc = getNodeSize(db, pRtree, isCreate, pzErr); 1144 + if( rc ) goto geopolyInit_fail; 1145 + rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate); 1146 + if( rc ){ 1147 + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); 1148 + goto geopolyInit_fail; 1149 + } 1150 + 1151 + *ppVtab = (sqlite3_vtab *)pRtree; 1152 + return SQLITE_OK; 1153 + 1154 +geopolyInit_fail: 1155 + if( rc==SQLITE_OK ) rc = SQLITE_ERROR; 1156 + assert( *ppVtab==0 ); 1157 + assert( pRtree->nBusy==1 ); 1158 + rtreeRelease(pRtree); 1159 + return rc; 1160 +} 1161 + 1162 + 1163 +/* 1164 +** GEOPOLY virtual table module xCreate method. 1165 +*/ 1166 +static int geopolyCreate( 1167 + sqlite3 *db, 1168 + void *pAux, 1169 + int argc, const char *const*argv, 1170 + sqlite3_vtab **ppVtab, 1171 + char **pzErr 1172 +){ 1173 + return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1); 1174 +} 1175 + 1176 +/* 1177 +** GEOPOLY virtual table module xConnect method. 1178 +*/ 1179 +static int geopolyConnect( 1180 + sqlite3 *db, 1181 + void *pAux, 1182 + int argc, const char *const*argv, 1183 + sqlite3_vtab **ppVtab, 1184 + char **pzErr 1185 +){ 1186 + return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0); 1187 +} 1188 + 1189 + 1190 +/* 1191 +** GEOPOLY virtual table module xFilter method. 1192 +** 1193 +** Query plans: 1194 +** 1195 +** 1 rowid lookup 1196 +** 2 search for objects overlapping the same bounding box 1197 +** that contains polygon argv[0] 1198 +** 3 search for objects overlapping the same bounding box 1199 +** that contains polygon argv[0] 1200 +** 4 full table scan 1201 +*/ 1202 +static int geopolyFilter( 1203 + sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */ 1204 + int idxNum, /* Query plan */ 1205 + const char *idxStr, /* Not Used */ 1206 + int argc, sqlite3_value **argv /* Parameters to the query plan */ 1207 +){ 1208 + Rtree *pRtree = (Rtree *)pVtabCursor->pVtab; 1209 + RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor; 1210 + RtreeNode *pRoot = 0; 1211 + int rc = SQLITE_OK; 1212 + int iCell = 0; 1213 + sqlite3_stmt *pStmt; 1214 + 1215 + rtreeReference(pRtree); 1216 + 1217 + /* Reset the cursor to the same state as rtreeOpen() leaves it in. */ 1218 + freeCursorConstraints(pCsr); 1219 + sqlite3_free(pCsr->aPoint); 1220 + pStmt = pCsr->pReadAux; 1221 + memset(pCsr, 0, sizeof(RtreeCursor)); 1222 + pCsr->base.pVtab = (sqlite3_vtab*)pRtree; 1223 + pCsr->pReadAux = pStmt; 1224 + 1225 + pCsr->iStrategy = idxNum; 1226 + if( idxNum==1 ){ 1227 + /* Special case - lookup by rowid. */ 1228 + RtreeNode *pLeaf; /* Leaf on which the required cell resides */ 1229 + RtreeSearchPoint *p; /* Search point for the leaf */ 1230 + i64 iRowid = sqlite3_value_int64(argv[0]); 1231 + i64 iNode = 0; 1232 + rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode); 1233 + if( rc==SQLITE_OK && pLeaf!=0 ){ 1234 + p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0); 1235 + assert( p!=0 ); /* Always returns pCsr->sPoint */ 1236 + pCsr->aNode[0] = pLeaf; 1237 + p->id = iNode; 1238 + p->eWithin = PARTLY_WITHIN; 1239 + rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell); 1240 + p->iCell = (u8)iCell; 1241 + RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:"); 1242 + }else{ 1243 + pCsr->atEOF = 1; 1244 + } 1245 + }else{ 1246 + /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array 1247 + ** with the configured constraints. 1248 + */ 1249 + rc = nodeAcquire(pRtree, 1, 0, &pRoot); 1250 + if( rc==SQLITE_OK && idxNum<=3 ){ 1251 + RtreeCoord bbox[4]; 1252 + RtreeConstraint *p; 1253 + assert( argc==1 ); 1254 + geopolyBBox(0, argv[0], bbox, &rc); 1255 + if( rc ){ 1256 + goto geopoly_filter_end; 1257 + } 1258 + pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4); 1259 + pCsr->nConstraint = 4; 1260 + if( p==0 ){ 1261 + rc = SQLITE_NOMEM; 1262 + }else{ 1263 + memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4); 1264 + memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1)); 1265 + if( idxNum==2 ){ 1266 + /* Overlap query */ 1267 + p->op = 'B'; 1268 + p->iCoord = 0; 1269 + p->u.rValue = bbox[1].f; 1270 + p++; 1271 + p->op = 'D'; 1272 + p->iCoord = 1; 1273 + p->u.rValue = bbox[0].f; 1274 + p++; 1275 + p->op = 'B'; 1276 + p->iCoord = 2; 1277 + p->u.rValue = bbox[3].f; 1278 + p++; 1279 + p->op = 'D'; 1280 + p->iCoord = 3; 1281 + p->u.rValue = bbox[2].f; 1282 + }else{ 1283 + /* Within query */ 1284 + p->op = 'D'; 1285 + p->iCoord = 0; 1286 + p->u.rValue = bbox[0].f; 1287 + p++; 1288 + p->op = 'B'; 1289 + p->iCoord = 1; 1290 + p->u.rValue = bbox[1].f; 1291 + p++; 1292 + p->op = 'D'; 1293 + p->iCoord = 2; 1294 + p->u.rValue = bbox[2].f; 1295 + p++; 1296 + p->op = 'B'; 1297 + p->iCoord = 3; 1298 + p->u.rValue = bbox[3].f; 1299 + } 1300 + } 1301 + } 1302 + if( rc==SQLITE_OK ){ 1303 + RtreeSearchPoint *pNew; 1304 + pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1)); 1305 + if( pNew==0 ){ 1306 + rc = SQLITE_NOMEM; 1307 + goto geopoly_filter_end; 1308 + } 1309 + pNew->id = 1; 1310 + pNew->iCell = 0; 1311 + pNew->eWithin = PARTLY_WITHIN; 1312 + assert( pCsr->bPoint==1 ); 1313 + pCsr->aNode[0] = pRoot; 1314 + pRoot = 0; 1315 + RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:"); 1316 + rc = rtreeStepToLeaf(pCsr); 1317 + } 1318 + } 1319 + 1320 +geopoly_filter_end: 1321 + nodeRelease(pRtree, pRoot); 1322 + rtreeRelease(pRtree); 1323 + return rc; 1324 +} 1325 + 1326 +/* 1327 +** Rtree virtual table module xBestIndex method. There are three 1328 +** table scan strategies to choose from (in order from most to 1329 +** least desirable): 1330 +** 1331 +** idxNum idxStr Strategy 1332 +** ------------------------------------------------ 1333 +** 1 "rowid" Direct lookup by rowid. 1334 +** 2 "rtree" R-tree overlap query using geopoly_overlap() 1335 +** 3 "rtree" R-tree within query using geopoly_within() 1336 +** 4 "fullscan" full-table scan. 1337 +** ------------------------------------------------ 1338 +*/ 1339 +static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ 1340 + int ii; 1341 + int iRowidTerm = -1; 1342 + int iFuncTerm = -1; 1343 + int idxNum = 0; 1344 + 1345 + for(ii=0; ii<pIdxInfo->nConstraint; ii++){ 1346 + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii]; 1347 + if( !p->usable ) continue; 1348 + if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ 1349 + iRowidTerm = ii; 1350 + break; 1351 + } 1352 + if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ 1353 + /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap() 1354 + ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within(). 1355 + ** See geopolyFindFunction() */ 1356 + iFuncTerm = ii; 1357 + idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2; 1358 + } 1359 + } 1360 + 1361 + if( iRowidTerm>=0 ){ 1362 + pIdxInfo->idxNum = 1; 1363 + pIdxInfo->idxStr = "rowid"; 1364 + pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1; 1365 + pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1; 1366 + pIdxInfo->estimatedCost = 30.0; 1367 + pIdxInfo->estimatedRows = 1; 1368 + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; 1369 + return SQLITE_OK; 1370 + } 1371 + if( iFuncTerm>=0 ){ 1372 + pIdxInfo->idxNum = idxNum; 1373 + pIdxInfo->idxStr = "rtree"; 1374 + pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1; 1375 + pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0; 1376 + pIdxInfo->estimatedCost = 300.0; 1377 + pIdxInfo->estimatedRows = 10; 1378 + return SQLITE_OK; 1379 + } 1380 + pIdxInfo->idxNum = 4; 1381 + pIdxInfo->idxStr = "fullscan"; 1382 + pIdxInfo->estimatedCost = 3000000.0; 1383 + pIdxInfo->estimatedRows = 100000; 1384 + return SQLITE_OK; 1385 +} 1386 + 1387 + 1388 +/* 1389 +** GEOPOLY virtual table module xColumn method. 1390 +*/ 1391 +static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ 1392 + Rtree *pRtree = (Rtree *)cur->pVtab; 1393 + RtreeCursor *pCsr = (RtreeCursor *)cur; 1394 + RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr); 1395 + int rc = SQLITE_OK; 1396 + RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc); 1397 + 1398 + if( rc ) return rc; 1399 + if( p==0 ) return SQLITE_OK; 1400 + if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK; 1401 + if( i<=pRtree->nAux ){ 1402 + if( !pCsr->bAuxValid ){ 1403 + if( pCsr->pReadAux==0 ){ 1404 + rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0, 1405 + &pCsr->pReadAux, 0); 1406 + if( rc ) return rc; 1407 + } 1408 + sqlite3_bind_int64(pCsr->pReadAux, 1, 1409 + nodeGetRowid(pRtree, pNode, p->iCell)); 1410 + rc = sqlite3_step(pCsr->pReadAux); 1411 + if( rc==SQLITE_ROW ){ 1412 + pCsr->bAuxValid = 1; 1413 + }else{ 1414 + sqlite3_reset(pCsr->pReadAux); 1415 + if( rc==SQLITE_DONE ) rc = SQLITE_OK; 1416 + return rc; 1417 + } 1418 + } 1419 + sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2)); 1420 + } 1421 + return SQLITE_OK; 1422 +} 1423 + 1424 + 1425 +/* 1426 +** The xUpdate method for GEOPOLY module virtual tables. 1427 +** 1428 +** For DELETE: 1429 +** 1430 +** argv[0] = the rowid to be deleted 1431 +** 1432 +** For INSERT: 1433 +** 1434 +** argv[0] = SQL NULL 1435 +** argv[1] = rowid to insert, or an SQL NULL to select automatically 1436 +** argv[2] = _shape column 1437 +** argv[3] = first application-defined column.... 1438 +** 1439 +** For UPDATE: 1440 +** 1441 +** argv[0] = rowid to modify. Never NULL 1442 +** argv[1] = rowid after the change. Never NULL 1443 +** argv[2] = new value for _shape 1444 +** argv[3] = new value for first application-defined column.... 1445 +*/ 1446 +static int geopolyUpdate( 1447 + sqlite3_vtab *pVtab, 1448 + int nData, 1449 + sqlite3_value **aData, 1450 + sqlite_int64 *pRowid 1451 +){ 1452 + Rtree *pRtree = (Rtree *)pVtab; 1453 + int rc = SQLITE_OK; 1454 + RtreeCell cell; /* New cell to insert if nData>1 */ 1455 + i64 oldRowid; /* The old rowid */ 1456 + int oldRowidValid; /* True if oldRowid is valid */ 1457 + i64 newRowid; /* The new rowid */ 1458 + int newRowidValid; /* True if newRowid is valid */ 1459 + int coordChange = 0; /* Change in coordinates */ 1460 + 1461 + if( pRtree->nNodeRef ){ 1462 + /* Unable to write to the btree while another cursor is reading from it, 1463 + ** since the write might do a rebalance which would disrupt the read 1464 + ** cursor. */ 1465 + return SQLITE_LOCKED_VTAB; 1466 + } 1467 + rtreeReference(pRtree); 1468 + assert(nData>=1); 1469 + 1470 + oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;; 1471 + oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0; 1472 + newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL; 1473 + newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0; 1474 + cell.iRowid = newRowid; 1475 + 1476 + if( nData>1 /* not a DELETE */ 1477 + && (!oldRowidValid /* INSERT */ 1478 + || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */ 1479 + || oldRowid!=newRowid) /* Rowid change */ 1480 + ){ 1481 + geopolyBBox(0, aData[2], cell.aCoord, &rc); 1482 + if( rc ){ 1483 + if( rc==SQLITE_ERROR ){ 1484 + pVtab->zErrMsg = 1485 + sqlite3_mprintf("_shape does not contain a valid polygon"); 1486 + } 1487 + goto geopoly_update_end; 1488 + } 1489 + coordChange = 1; 1490 + 1491 + /* If a rowid value was supplied, check if it is already present in 1492 + ** the table. If so, the constraint has failed. */ 1493 + if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){ 1494 + int steprc; 1495 + sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid); 1496 + steprc = sqlite3_step(pRtree->pReadRowid); 1497 + rc = sqlite3_reset(pRtree->pReadRowid); 1498 + if( SQLITE_ROW==steprc ){ 1499 + if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){ 1500 + rc = rtreeDeleteRowid(pRtree, cell.iRowid); 1501 + }else{ 1502 + rc = rtreeConstraintError(pRtree, 0); 1503 + } 1504 + } 1505 + } 1506 + } 1507 + 1508 + /* If aData[0] is not an SQL NULL value, it is the rowid of a 1509 + ** record to delete from the r-tree table. The following block does 1510 + ** just that. 1511 + */ 1512 + if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){ 1513 + rc = rtreeDeleteRowid(pRtree, oldRowid); 1514 + } 1515 + 1516 + /* If the aData[] array contains more than one element, elements 1517 + ** (aData[2]..aData[argc-1]) contain a new record to insert into 1518 + ** the r-tree structure. 1519 + */ 1520 + if( rc==SQLITE_OK && nData>1 && coordChange ){ 1521 + /* Insert the new record into the r-tree */ 1522 + RtreeNode *pLeaf = 0; 1523 + if( !newRowidValid ){ 1524 + rc = rtreeNewRowid(pRtree, &cell.iRowid); 1525 + } 1526 + *pRowid = cell.iRowid; 1527 + if( rc==SQLITE_OK ){ 1528 + rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); 1529 + } 1530 + if( rc==SQLITE_OK ){ 1531 + int rc2; 1532 + pRtree->iReinsertHeight = -1; 1533 + rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0); 1534 + rc2 = nodeRelease(pRtree, pLeaf); 1535 + if( rc==SQLITE_OK ){ 1536 + rc = rc2; 1537 + } 1538 + } 1539 + } 1540 + 1541 + /* Change the data */ 1542 + if( rc==SQLITE_OK ){ 1543 + sqlite3_stmt *pUp = pRtree->pWriteAux; 1544 + int jj; 1545 + int nChange = 0; 1546 + sqlite3_bind_int64(pUp, 1, cell.iRowid); 1547 + assert( pRtree->nAux>=1 ); 1548 + if( sqlite3_value_nochange(aData[2]) ){ 1549 + sqlite3_bind_null(pUp, 2); 1550 + }else{ 1551 + sqlite3_bind_value(pUp, 2, aData[2]); 1552 + nChange = 1; 1553 + } 1554 + for(jj=1; jj<pRtree->nAux; jj++){ 1555 + nChange++; 1556 + sqlite3_bind_value(pUp, jj+2, aData[jj+2]); 1557 + } 1558 + if( nChange ){ 1559 + sqlite3_step(pUp); 1560 + rc = sqlite3_reset(pUp); 1561 + } 1562 + } 1563 + 1564 +geopoly_update_end: 1565 + rtreeRelease(pRtree); 1566 + return rc; 1567 +} 1568 + 1569 +/* 1570 +** Report that geopoly_overlap() is an overloaded function suitable 1571 +** for use in xBestIndex. 1572 +*/ 1573 +static int geopolyFindFunction( 1574 + sqlite3_vtab *pVtab, 1575 + int nArg, 1576 + const char *zName, 1577 + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), 1578 + void **ppArg 1579 +){ 1580 + if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){ 1581 + *pxFunc = geopolyOverlapFunc; 1582 + *ppArg = 0; 1583 + return SQLITE_INDEX_CONSTRAINT_FUNCTION; 1584 + } 1585 + if( sqlite3_stricmp(zName, "geopoly_within")==0 ){ 1586 + *pxFunc = geopolyWithinFunc; 1587 + *ppArg = 0; 1588 + return SQLITE_INDEX_CONSTRAINT_FUNCTION+1; 1589 + } 1590 + return 0; 1591 +} 1592 + 1593 + 1594 +static sqlite3_module geopolyModule = { 1595 + 2, /* iVersion */ 1596 + geopolyCreate, /* xCreate - create a table */ 1597 + geopolyConnect, /* xConnect - connect to an existing table */ 1598 + geopolyBestIndex, /* xBestIndex - Determine search strategy */ 1599 + rtreeDisconnect, /* xDisconnect - Disconnect from a table */ 1600 + rtreeDestroy, /* xDestroy - Drop a table */ 1601 + rtreeOpen, /* xOpen - open a cursor */ 1602 + rtreeClose, /* xClose - close a cursor */ 1603 + geopolyFilter, /* xFilter - configure scan constraints */ 1604 + rtreeNext, /* xNext - advance a cursor */ 1605 + rtreeEof, /* xEof */ 1606 + geopolyColumn, /* xColumn - read data */ 1607 + rtreeRowid, /* xRowid - read data */ 1608 + geopolyUpdate, /* xUpdate - write data */ 1609 + rtreeBeginTransaction, /* xBegin - begin transaction */ 1610 + rtreeEndTransaction, /* xSync - sync transaction */ 1611 + rtreeEndTransaction, /* xCommit - commit transaction */ 1612 + rtreeEndTransaction, /* xRollback - rollback transaction */ 1613 + geopolyFindFunction, /* xFindFunction - function overloading */ 1614 + rtreeRename, /* xRename - rename the table */ 1615 + rtreeSavepoint, /* xSavepoint */ 1616 + 0, /* xRelease */ 1617 + 0, /* xRollbackTo */ 1618 +}; 1619 + 1620 +static int sqlite3_geopoly_init(sqlite3 *db){ 1621 + int rc = SQLITE_OK; 1622 + static const struct { 1623 + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); 1624 + int nArg; 1625 + const char *zName; 1626 + } aFunc[] = { 1627 + { geopolyAreaFunc, 1, "geopoly_area" }, 1628 + { geopolyBlobFunc, 1, "geopoly_blob" }, 1629 + { geopolyJsonFunc, 1, "geopoly_json" }, 1630 + { geopolySvgFunc, -1, "geopoly_svg" }, 1631 + { geopolyWithinFunc, 2, "geopoly_within" }, 1632 + { geopolyContainsPointFunc, 3, "geopoly_contains_point" }, 1633 + { geopolyOverlapFunc, 2, "geopoly_overlap" }, 1634 + { geopolyDebugFunc, 1, "geopoly_debug" }, 1635 + { geopolyBBoxFunc, 1, "geopoly_bbox" }, 1636 + { geopolyXformFunc, 7, "geopoly_xform" }, 1637 + }; 1638 + static const struct { 1639 + void (*xStep)(sqlite3_context*,int,sqlite3_value**); 1640 + void (*xFinal)(sqlite3_context*); 1641 + const char *zName; 1642 + } aAgg[] = { 1643 + { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" }, 1644 + }; 1645 + int i; 1646 + for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ 1647 + rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, 1648 + SQLITE_UTF8, 0, 1649 + aFunc[i].xFunc, 0, 0); 1650 + } 1651 + for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ 1652 + rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0, 1653 + 0, aAgg[i].xStep, aAgg[i].xFinal); 1654 + } 1655 + if( rc==SQLITE_OK ){ 1656 + rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0); 1657 + } 1658 + return rc; 1659 +}
Changes to ext/rtree/rtree.c.
123 123 int iNodeSize; /* Size in bytes of each node in the node table */ 124 124 u8 nDim; /* Number of dimensions */ 125 125 u8 nDim2; /* Twice the number of dimensions */ 126 126 u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */ 127 127 u8 nBytesPerCell; /* Bytes consumed per cell */ 128 128 u8 inWrTrans; /* True if inside write transaction */ 129 129 u8 nAux; /* # of auxiliary columns in %_rowid */ 130 + u8 nAuxNotNull; /* Number of initial not-null aux columns */ 130 131 int iDepth; /* Current depth of the r-tree structure */ 131 132 char *zDb; /* Name of database containing r-tree table */ 132 133 char *zName; /* Name of r-tree table */ 133 134 u32 nBusy; /* Current number of users of this structure */ 134 135 i64 nRowEst; /* Estimated number of rows in this table */ 135 136 u32 nCursor; /* Number of open cursors */ 136 137 u32 nNodeRef; /* Number RtreeNodes with positive nRef */ ................................................................................ 2889 2890 } 2890 2891 return rc; 2891 2892 } 2892 2893 2893 2894 /* 2894 2895 ** Select a currently unused rowid for a new r-tree record. 2895 2896 */ 2896 -static int newRowid(Rtree *pRtree, i64 *piRowid){ 2897 +static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){ 2897 2898 int rc; 2898 2899 sqlite3_bind_null(pRtree->pWriteRowid, 1); 2899 2900 sqlite3_bind_null(pRtree->pWriteRowid, 2); 2900 2901 sqlite3_step(pRtree->pWriteRowid); 2901 2902 rc = sqlite3_reset(pRtree->pWriteRowid); 2902 2903 *piRowid = sqlite3_last_insert_rowid(pRtree->db); 2903 2904 return rc; ................................................................................ 3176 3177 */ 3177 3178 if( rc==SQLITE_OK && nData>1 ){ 3178 3179 /* Insert the new record into the r-tree */ 3179 3180 RtreeNode *pLeaf = 0; 3180 3181 3181 3182 /* Figure out the rowid of the new row. */ 3182 3183 if( bHaveRowid==0 ){ 3183 - rc = newRowid(pRtree, &cell.iRowid); 3184 + rc = rtreeNewRowid(pRtree, &cell.iRowid); 3184 3185 } 3185 3186 *pRowid = cell.iRowid; 3186 3187 3187 3188 if( rc==SQLITE_OK ){ 3188 3189 rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf); 3189 3190 } 3190 3191 if( rc==SQLITE_OK ){ ................................................................................ 3449 3450 }else{ 3450 3451 sqlite3_str *p = sqlite3_str_new(db); 3451 3452 int ii; 3452 3453 char *zSql; 3453 3454 sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix); 3454 3455 for(ii=0; ii<pRtree->nAux; ii++){ 3455 3456 if( ii ) sqlite3_str_append(p, ",", 1); 3456 - sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); 3457 + if( ii<pRtree->nAuxNotNull ){ 3458 + sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii); 3459 + }else{ 3460 + sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2); 3461 + } 3457 3462 } 3458 3463 sqlite3_str_appendf(p, " WHERE rowid=?1"); 3459 3464 zSql = sqlite3_str_finish(p); 3460 3465 if( zSql==0 ){ 3461 3466 rc = SQLITE_NOMEM; 3462 3467 }else{ 3463 3468 rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT, ................................................................................ 4218 4223 }else{ 4219 4224 sqlite3_result_error_code(ctx, rc); 4220 4225 } 4221 4226 sqlite3_free(zReport); 4222 4227 } 4223 4228 } 4224 4229 4230 +/* Conditionally include the geopoly code */ 4231 +#ifdef SQLITE_ENABLE_GEOPOLY 4232 +# include "geopoly.c" 4233 +#endif 4225 4234 4226 4235 /* 4227 4236 ** Register the r-tree module with database handle db. This creates the 4228 4237 ** virtual table module "rtree" and the debugging/analysis scalar 4229 4238 ** function "rtreenode". 4230 4239 */ 4231 4240 int sqlite3RtreeInit(sqlite3 *db){ ................................................................................ 4247 4256 #endif 4248 4257 rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); 4249 4258 } 4250 4259 if( rc==SQLITE_OK ){ 4251 4260 void *c = (void *)RTREE_COORD_INT32; 4252 4261 rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); 4253 4262 } 4263 +#ifdef SQLITE_ENABLE_GEOPOLY 4264 + if( rc==SQLITE_OK ){ 4265 + rc = sqlite3_geopoly_init(db); 4266 + } 4267 +#endif 4254 4268 4255 4269 return rc; 4256 4270 } 4257 4271 4258 4272 /* 4259 4273 ** This routine deletes the RtreeGeomCallback object that was attached 4260 4274 ** one of the SQL functions create by sqlite3_rtree_geometry_callback()
Added ext/rtree/visual01.txt.
1 +#!sqlite3 2 +# 3 +# This is a visual test case for the geopoly virtual table. 4 +# 5 +# Run this script in the sqlite3 CLI, and redirect output into an 6 +# HTML file. This display the HTML in a webbrowser. 7 +# 8 + 9 +/* Test data. 10 +** Lots of shapes to be displayed over a 1000x800 canvas. 11 +*/ 12 +CREATE TEMP TABLE basis(name TEXT, jshape TEXT); 13 +INSERT INTO basis(name,jshape) VALUES 14 + ('box-20','[[0,0],[20,0],[20,20],[0,20],[0,0]]'), 15 + ('house-70','[[0,0],[50,0],[50,50],[25,70],[0,50],[0,0]]'), 16 + ('line-40','[[0,0],[40,0],[40,5],[0,5],[0,0]]'), 17 + ('line-80','[[0,0],[80,0],[80,7],[0,7],[0,0]]'), 18 + ('arrow-50','[[0,0],[25,25],[0,50],[15,25],[0,0]]'), 19 + ('triangle-30','[[0,0],[30,0],[15,30],[0,0]]'), 20 + ('angle-30','[[0,0],[30,0],[30,30],[26,30],[26,4],[0,4],[0,0]]'), 21 + ('star-10','[[1,0],[5,2],[9,0],[7,4],[10,8],[7,7],[5,10],[3,7],[0,8],[3,4],[1,0]]'); 22 +CREATE TEMP TABLE xform(A,B,C,D,clr); 23 +INSERT INTO xform(A,B,clr) VALUES 24 + (1,0,'black'), 25 + (0.707,0.707,'blue'), 26 + (0.5,0.866,'red'), 27 + (-0.866,0.5,'green'); 28 +CREATE TEMP TABLE xyoff(id1,id2,xoff,yoff,PRIMARY KEY(id1,id2,xoff,yoff)) 29 + WITHOUT ROWID; 30 +INSERT INTO xyoff VALUES(1,1,811,659); 31 +INSERT INTO xyoff VALUES(1,1,235,550); 32 +INSERT INTO xyoff VALUES(1,1,481,620); 33 +INSERT INTO xyoff VALUES(1,1,106,494); 34 +INSERT INTO xyoff VALUES(1,1,487,106); 35 +INSERT INTO xyoff VALUES(1,1,817,595); 36 +INSERT INTO xyoff VALUES(1,1,240,504); 37 +INSERT INTO xyoff VALUES(1,1,806,457); 38 +INSERT INTO xyoff VALUES(1,1,608,107); 39 +INSERT INTO xyoff VALUES(1,1,768,662); 40 +INSERT INTO xyoff VALUES(1,2,808,528); 41 +INSERT INTO xyoff VALUES(1,2,768,528); 42 +INSERT INTO xyoff VALUES(1,2,771,171); 43 +INSERT INTO xyoff VALUES(1,2,275,671); 44 +INSERT INTO xyoff VALUES(1,2,326,336); 45 +INSERT INTO xyoff VALUES(1,2,690,688); 46 +INSERT INTO xyoff VALUES(1,2,597,239); 47 +INSERT INTO xyoff VALUES(1,2,317,528); 48 +INSERT INTO xyoff VALUES(1,2,366,223); 49 +INSERT INTO xyoff VALUES(1,2,621,154); 50 +INSERT INTO xyoff VALUES(1,3,829,469); 51 +INSERT INTO xyoff VALUES(1,3,794,322); 52 +INSERT INTO xyoff VALUES(1,3,358,387); 53 +INSERT INTO xyoff VALUES(1,3,184,444); 54 +INSERT INTO xyoff VALUES(1,3,729,500); 55 +INSERT INTO xyoff VALUES(1,3,333,523); 56 +INSERT INTO xyoff VALUES(1,3,117,595); 57 +INSERT INTO xyoff VALUES(1,3,496,201); 58 +INSERT INTO xyoff VALUES(1,3,818,601); 59 +INSERT INTO xyoff VALUES(1,3,541,343); 60 +INSERT INTO xyoff VALUES(1,4,603,248); 61 +INSERT INTO xyoff VALUES(1,4,761,649); 62 +INSERT INTO xyoff VALUES(1,4,611,181); 63 +INSERT INTO xyoff VALUES(1,4,607,233); 64 +INSERT INTO xyoff VALUES(1,4,860,206); 65 +INSERT INTO xyoff VALUES(1,4,310,231); 66 +INSERT INTO xyoff VALUES(1,4,727,539); 67 +INSERT INTO xyoff VALUES(1,4,660,661); 68 +INSERT INTO xyoff VALUES(1,4,403,133); 69 +INSERT INTO xyoff VALUES(1,4,619,331); 70 +INSERT INTO xyoff VALUES(2,1,712,578); 71 +INSERT INTO xyoff VALUES(2,1,567,313); 72 +INSERT INTO xyoff VALUES(2,1,231,423); 73 +INSERT INTO xyoff VALUES(2,1,490,175); 74 +INSERT INTO xyoff VALUES(2,1,898,353); 75 +INSERT INTO xyoff VALUES(2,1,589,483); 76 +INSERT INTO xyoff VALUES(2,1,188,462); 77 +INSERT INTO xyoff VALUES(2,1,720,106); 78 +INSERT INTO xyoff VALUES(2,1,793,380); 79 +INSERT INTO xyoff VALUES(2,1,154,396); 80 +INSERT INTO xyoff VALUES(2,2,324,218); 81 +INSERT INTO xyoff VALUES(2,2,120,327); 82 +INSERT INTO xyoff VALUES(2,2,655,133); 83 +INSERT INTO xyoff VALUES(2,2,516,603); 84 +INSERT INTO xyoff VALUES(2,2,529,572); 85 +INSERT INTO xyoff VALUES(2,2,481,212); 86 +INSERT INTO xyoff VALUES(2,2,802,107); 87 +INSERT INTO xyoff VALUES(2,2,234,509); 88 +INSERT INTO xyoff VALUES(2,2,501,269); 89 +INSERT INTO xyoff VALUES(2,2,349,553); 90 +INSERT INTO xyoff VALUES(2,3,495,685); 91 +INSERT INTO xyoff VALUES(2,3,897,372); 92 +INSERT INTO xyoff VALUES(2,3,350,681); 93 +INSERT INTO xyoff VALUES(2,3,832,257); 94 +INSERT INTO xyoff VALUES(2,3,778,149); 95 +INSERT INTO xyoff VALUES(2,3,683,426); 96 +INSERT INTO xyoff VALUES(2,3,693,217); 97 +INSERT INTO xyoff VALUES(2,3,746,317); 98 +INSERT INTO xyoff VALUES(2,3,805,369); 99 +INSERT INTO xyoff VALUES(2,3,336,585); 100 +INSERT INTO xyoff VALUES(2,4,890,255); 101 +INSERT INTO xyoff VALUES(2,4,556,565); 102 +INSERT INTO xyoff VALUES(2,4,865,555); 103 +INSERT INTO xyoff VALUES(2,4,230,293); 104 +INSERT INTO xyoff VALUES(2,4,247,251); 105 +INSERT INTO xyoff VALUES(2,4,730,563); 106 +INSERT INTO xyoff VALUES(2,4,318,282); 107 +INSERT INTO xyoff VALUES(2,4,220,431); 108 +INSERT INTO xyoff VALUES(2,4,828,336); 109 +INSERT INTO xyoff VALUES(2,4,278,525); 110 +INSERT INTO xyoff VALUES(3,1,324,656); 111 +INSERT INTO xyoff VALUES(3,1,625,362); 112 +INSERT INTO xyoff VALUES(3,1,155,570); 113 +INSERT INTO xyoff VALUES(3,1,267,433); 114 +INSERT INTO xyoff VALUES(3,1,599,121); 115 +INSERT INTO xyoff VALUES(3,1,873,498); 116 +INSERT INTO xyoff VALUES(3,1,789,520); 117 +INSERT INTO xyoff VALUES(3,1,656,378); 118 +INSERT INTO xyoff VALUES(3,1,831,601); 119 +INSERT INTO xyoff VALUES(3,1,256,471); 120 +INSERT INTO xyoff VALUES(3,2,332,258); 121 +INSERT INTO xyoff VALUES(3,2,305,463); 122 +INSERT INTO xyoff VALUES(3,2,796,341); 123 +INSERT INTO xyoff VALUES(3,2,830,229); 124 +INSERT INTO xyoff VALUES(3,2,413,271); 125 +INSERT INTO xyoff VALUES(3,2,269,140); 126 +INSERT INTO xyoff VALUES(3,2,628,441); 127 +INSERT INTO xyoff VALUES(3,2,747,643); 128 +INSERT INTO xyoff VALUES(3,2,584,435); 129 +INSERT INTO xyoff VALUES(3,2,784,314); 130 +INSERT INTO xyoff VALUES(3,3,722,233); 131 +INSERT INTO xyoff VALUES(3,3,815,421); 132 +INSERT INTO xyoff VALUES(3,3,401,267); 133 +INSERT INTO xyoff VALUES(3,3,451,650); 134 +INSERT INTO xyoff VALUES(3,3,329,485); 135 +INSERT INTO xyoff VALUES(3,3,878,370); 136 +INSERT INTO xyoff VALUES(3,3,162,616); 137 +INSERT INTO xyoff VALUES(3,3,844,183); 138 +INSERT INTO xyoff VALUES(3,3,161,216); 139 +INSERT INTO xyoff VALUES(3,3,176,676); 140 +INSERT INTO xyoff VALUES(3,4,780,128); 141 +INSERT INTO xyoff VALUES(3,4,566,121); 142 +INSERT INTO xyoff VALUES(3,4,646,120); 143 +INSERT INTO xyoff VALUES(3,4,223,557); 144 +INSERT INTO xyoff VALUES(3,4,251,117); 145 +INSERT INTO xyoff VALUES(3,4,139,209); 146 +INSERT INTO xyoff VALUES(3,4,813,597); 147 +INSERT INTO xyoff VALUES(3,4,454,538); 148 +INSERT INTO xyoff VALUES(3,4,616,198); 149 +INSERT INTO xyoff VALUES(3,4,210,159); 150 +INSERT INTO xyoff VALUES(4,1,208,415); 151 +INSERT INTO xyoff VALUES(4,1,326,665); 152 +INSERT INTO xyoff VALUES(4,1,612,133); 153 +INSERT INTO xyoff VALUES(4,1,537,513); 154 +INSERT INTO xyoff VALUES(4,1,638,438); 155 +INSERT INTO xyoff VALUES(4,1,808,269); 156 +INSERT INTO xyoff VALUES(4,1,552,121); 157 +INSERT INTO xyoff VALUES(4,1,100,189); 158 +INSERT INTO xyoff VALUES(4,1,643,664); 159 +INSERT INTO xyoff VALUES(4,1,726,378); 160 +INSERT INTO xyoff VALUES(4,2,478,409); 161 +INSERT INTO xyoff VALUES(4,2,497,507); 162 +INSERT INTO xyoff VALUES(4,2,233,148); 163 +INSERT INTO xyoff VALUES(4,2,587,237); 164 +INSERT INTO xyoff VALUES(4,2,604,166); 165 +INSERT INTO xyoff VALUES(4,2,165,455); 166 +INSERT INTO xyoff VALUES(4,2,320,258); 167 +INSERT INTO xyoff VALUES(4,2,353,496); 168 +INSERT INTO xyoff VALUES(4,2,347,495); 169 +INSERT INTO xyoff VALUES(4,2,166,622); 170 +INSERT INTO xyoff VALUES(4,3,461,332); 171 +INSERT INTO xyoff VALUES(4,3,685,278); 172 +INSERT INTO xyoff VALUES(4,3,427,594); 173 +INSERT INTO xyoff VALUES(4,3,467,346); 174 +INSERT INTO xyoff VALUES(4,3,125,548); 175 +INSERT INTO xyoff VALUES(4,3,597,680); 176 +INSERT INTO xyoff VALUES(4,3,820,445); 177 +INSERT INTO xyoff VALUES(4,3,144,330); 178 +INSERT INTO xyoff VALUES(4,3,557,434); 179 +INSERT INTO xyoff VALUES(4,3,254,315); 180 +INSERT INTO xyoff VALUES(4,4,157,339); 181 +INSERT INTO xyoff VALUES(4,4,249,220); 182 +INSERT INTO xyoff VALUES(4,4,391,323); 183 +INSERT INTO xyoff VALUES(4,4,589,429); 184 +INSERT INTO xyoff VALUES(4,4,859,592); 185 +INSERT INTO xyoff VALUES(4,4,337,680); 186 +INSERT INTO xyoff VALUES(4,4,410,288); 187 +INSERT INTO xyoff VALUES(4,4,636,596); 188 +INSERT INTO xyoff VALUES(4,4,734,433); 189 +INSERT INTO xyoff VALUES(4,4,559,549); 190 +INSERT INTO xyoff VALUES(5,1,549,607); 191 +INSERT INTO xyoff VALUES(5,1,584,498); 192 +INSERT INTO xyoff VALUES(5,1,699,116); 193 +INSERT INTO xyoff VALUES(5,1,525,524); 194 +INSERT INTO xyoff VALUES(5,1,304,667); 195 +INSERT INTO xyoff VALUES(5,1,302,232); 196 +INSERT INTO xyoff VALUES(5,1,403,149); 197 +INSERT INTO xyoff VALUES(5,1,824,403); 198 +INSERT INTO xyoff VALUES(5,1,697,203); 199 +INSERT INTO xyoff VALUES(5,1,293,689); 200 +INSERT INTO xyoff VALUES(5,2,199,275); 201 +INSERT INTO xyoff VALUES(5,2,395,393); 202 +INSERT INTO xyoff VALUES(5,2,657,642); 203 +INSERT INTO xyoff VALUES(5,2,200,655); 204 +INSERT INTO xyoff VALUES(5,2,882,234); 205 +INSERT INTO xyoff VALUES(5,2,483,565); 206 +INSERT INTO xyoff VALUES(5,2,755,640); 207 +INSERT INTO xyoff VALUES(5,2,810,305); 208 +INSERT INTO xyoff VALUES(5,2,731,655); 209 +INSERT INTO xyoff VALUES(5,2,466,690); 210 +INSERT INTO xyoff VALUES(5,3,563,584); 211 +INSERT INTO xyoff VALUES(5,3,491,117); 212 +INSERT INTO xyoff VALUES(5,3,779,292); 213 +INSERT INTO xyoff VALUES(5,3,375,637); 214 +INSERT INTO xyoff VALUES(5,3,253,553); 215 +INSERT INTO xyoff VALUES(5,3,797,514); 216 +INSERT INTO xyoff VALUES(5,3,229,480); 217 +INSERT INTO xyoff VALUES(5,3,257,194); 218 +INSERT INTO xyoff VALUES(5,3,449,555); 219 +INSERT INTO xyoff VALUES(5,3,849,630); 220 +INSERT INTO xyoff VALUES(5,4,329,286); 221 +INSERT INTO xyoff VALUES(5,4,640,197); 222 +INSERT INTO xyoff VALUES(5,4,104,150); 223 +INSERT INTO xyoff VALUES(5,4,438,272); 224 +INSERT INTO xyoff VALUES(5,4,773,226); 225 +INSERT INTO xyoff VALUES(5,4,441,650); 226 +INSERT INTO xyoff VALUES(5,4,242,340); 227 +INSERT INTO xyoff VALUES(5,4,301,435); 228 +INSERT INTO xyoff VALUES(5,4,171,397); 229 +INSERT INTO xyoff VALUES(5,4,541,619); 230 +INSERT INTO xyoff VALUES(6,1,651,301); 231 +INSERT INTO xyoff VALUES(6,1,637,137); 232 +INSERT INTO xyoff VALUES(6,1,765,643); 233 +INSERT INTO xyoff VALUES(6,1,173,296); 234 +INSERT INTO xyoff VALUES(6,1,263,192); 235 +INSERT INTO xyoff VALUES(6,1,791,302); 236 +INSERT INTO xyoff VALUES(6,1,860,601); 237 +INSERT INTO xyoff VALUES(6,1,780,445); 238 +INSERT INTO xyoff VALUES(6,1,462,214); 239 +INSERT INTO xyoff VALUES(6,1,802,207); 240 +INSERT INTO xyoff VALUES(6,2,811,685); 241 +INSERT INTO xyoff VALUES(6,2,533,531); 242 +INSERT INTO xyoff VALUES(6,2,390,614); 243 +INSERT INTO xyoff VALUES(6,2,260,580); 244 +INSERT INTO xyoff VALUES(6,2,116,377); 245 +INSERT INTO xyoff VALUES(6,2,860,458); 246 +INSERT INTO xyoff VALUES(6,2,438,590); 247 +INSERT INTO xyoff VALUES(6,2,604,562); 248 +INSERT INTO xyoff VALUES(6,2,241,242); 249 +INSERT INTO xyoff VALUES(6,2,667,298); 250 +INSERT INTO xyoff VALUES(6,3,787,698); 251 +INSERT INTO xyoff VALUES(6,3,868,521); 252 +INSERT INTO xyoff VALUES(6,3,412,587); 253 +INSERT INTO xyoff VALUES(6,3,640,131); 254 +INSERT INTO xyoff VALUES(6,3,748,410); 255 +INSERT INTO xyoff VALUES(6,3,257,244); 256 +INSERT INTO xyoff VALUES(6,3,411,195); 257 +INSERT INTO xyoff VALUES(6,3,464,356); 258 +INSERT INTO xyoff VALUES(6,3,157,339); 259 +INSERT INTO xyoff VALUES(6,3,434,505); 260 +INSERT INTO xyoff VALUES(6,4,480,671); 261 +INSERT INTO xyoff VALUES(6,4,519,228); 262 +INSERT INTO xyoff VALUES(6,4,404,513); 263 +INSERT INTO xyoff VALUES(6,4,120,538); 264 +INSERT INTO xyoff VALUES(6,4,403,663); 265 +INSERT INTO xyoff VALUES(6,4,477,677); 266 +INSERT INTO xyoff VALUES(6,4,690,154); 267 +INSERT INTO xyoff VALUES(6,4,606,498); 268 +INSERT INTO xyoff VALUES(6,4,430,665); 269 +INSERT INTO xyoff VALUES(6,4,499,273); 270 +INSERT INTO xyoff VALUES(7,1,118,526); 271 +INSERT INTO xyoff VALUES(7,1,817,522); 272 +INSERT INTO xyoff VALUES(7,1,388,638); 273 +INSERT INTO xyoff VALUES(7,1,181,265); 274 +INSERT INTO xyoff VALUES(7,1,442,332); 275 +INSERT INTO xyoff VALUES(7,1,475,282); 276 +INSERT INTO xyoff VALUES(7,1,722,633); 277 +INSERT INTO xyoff VALUES(7,1,104,394); 278 +INSERT INTO xyoff VALUES(7,1,631,262); 279 +INSERT INTO xyoff VALUES(7,1,372,392); 280 +INSERT INTO xyoff VALUES(7,2,600,413); 281 +INSERT INTO xyoff VALUES(7,2,386,223); 282 +INSERT INTO xyoff VALUES(7,2,839,174); 283 +INSERT INTO xyoff VALUES(7,2,293,410); 284 +INSERT INTO xyoff VALUES(7,2,281,391); 285 +INSERT INTO xyoff VALUES(7,2,859,387); 286 +INSERT INTO xyoff VALUES(7,2,478,347); 287 +INSERT INTO xyoff VALUES(7,2,646,690); 288 +INSERT INTO xyoff VALUES(7,2,713,234); 289 +INSERT INTO xyoff VALUES(7,2,199,588); 290 +INSERT INTO xyoff VALUES(7,3,389,256); 291 +INSERT INTO xyoff VALUES(7,3,349,542); 292 +INSERT INTO xyoff VALUES(7,3,363,345); 293 +INSERT INTO xyoff VALUES(7,3,751,302); 294 +INSERT INTO xyoff VALUES(7,3,423,386); 295 +INSERT INTO xyoff VALUES(7,3,267,444); 296 +INSERT INTO xyoff VALUES(7,3,243,182); 297 +INSERT INTO xyoff VALUES(7,3,453,658); 298 +INSERT INTO xyoff VALUES(7,3,126,345); 299 +INSERT INTO xyoff VALUES(7,3,120,472); 300 +INSERT INTO xyoff VALUES(7,4,359,654); 301 +INSERT INTO xyoff VALUES(7,4,339,516); 302 +INSERT INTO xyoff VALUES(7,4,710,452); 303 +INSERT INTO xyoff VALUES(7,4,810,560); 304 +INSERT INTO xyoff VALUES(7,4,644,692); 305 +INSERT INTO xyoff VALUES(7,4,826,327); 306 +INSERT INTO xyoff VALUES(7,4,465,462); 307 +INSERT INTO xyoff VALUES(7,4,310,456); 308 +INSERT INTO xyoff VALUES(7,4,577,613); 309 +INSERT INTO xyoff VALUES(7,4,502,555); 310 +INSERT INTO xyoff VALUES(8,1,601,620); 311 +INSERT INTO xyoff VALUES(8,1,372,683); 312 +INSERT INTO xyoff VALUES(8,1,758,399); 313 +INSERT INTO xyoff VALUES(8,1,485,552); 314 +INSERT INTO xyoff VALUES(8,1,159,563); 315 +INSERT INTO xyoff VALUES(8,1,536,303); 316 +INSERT INTO xyoff VALUES(8,1,122,263); 317 +INSERT INTO xyoff VALUES(8,1,836,435); 318 +INSERT INTO xyoff VALUES(8,1,544,146); 319 +INSERT INTO xyoff VALUES(8,1,270,277); 320 +INSERT INTO xyoff VALUES(8,2,849,281); 321 +INSERT INTO xyoff VALUES(8,2,563,242); 322 +INSERT INTO xyoff VALUES(8,2,704,463); 323 +INSERT INTO xyoff VALUES(8,2,102,165); 324 +INSERT INTO xyoff VALUES(8,2,797,524); 325 +INSERT INTO xyoff VALUES(8,2,612,426); 326 +INSERT INTO xyoff VALUES(8,2,345,372); 327 +INSERT INTO xyoff VALUES(8,2,820,376); 328 +INSERT INTO xyoff VALUES(8,2,789,156); 329 +INSERT INTO xyoff VALUES(8,2,321,466); 330 +INSERT INTO xyoff VALUES(8,3,150,332); 331 +INSERT INTO xyoff VALUES(8,3,136,152); 332 +INSERT INTO xyoff VALUES(8,3,468,528); 333 +INSERT INTO xyoff VALUES(8,3,409,192); 334 +INSERT INTO xyoff VALUES(8,3,820,216); 335 +INSERT INTO xyoff VALUES(8,3,847,249); 336 +INSERT INTO xyoff VALUES(8,3,801,267); 337 +INSERT INTO xyoff VALUES(8,3,181,670); 338 +INSERT INTO xyoff VALUES(8,3,398,563); 339 +INSERT INTO xyoff VALUES(8,3,439,576); 340 +INSERT INTO xyoff VALUES(8,4,123,309); 341 +INSERT INTO xyoff VALUES(8,4,190,496); 342 +INSERT INTO xyoff VALUES(8,4,571,531); 343 +INSERT INTO xyoff VALUES(8,4,290,255); 344 +INSERT INTO xyoff VALUES(8,4,244,412); 345 +INSERT INTO xyoff VALUES(8,4,264,596); 346 +INSERT INTO xyoff VALUES(8,4,253,420); 347 +INSERT INTO xyoff VALUES(8,4,847,536); 348 +INSERT INTO xyoff VALUES(8,4,120,288); 349 +INSERT INTO xyoff VALUES(8,4,331,639); 350 + 351 +/* Create the geopoly object from test data above */ 352 +CREATE VIRTUAL TABLE geo1 USING geopoly(type,clr); 353 +INSERT INTO geo1(_shape,type,clr) 354 + SELECT geopoly_xform(jshape,A,B,-B,A,xoff,yoff), basis.name, xform.clr 355 + FROM basis, xform, xyoff 356 + WHERE xyoff.id1=basis.rowid AND xyoff.id2=xform.rowid; 357 + 358 + 359 +/* Query polygon */ 360 +CREATE TEMP TABLE querypoly(poly JSON, clr TEXT); 361 +INSERT INTO querypoly(clr, poly) VALUES 362 + ('orange', '[[300,300],[400,350],[500,250],[480,500],[400,480],[300,550],[280,450],[320,400],[280,350],[300,300]]'); 363 + 364 +/* Generate the HTML */ 365 +.print '<html>' 366 +.print '<h1>Everything</h1>' 367 +.print '<svg width="1000" height="800" style="border:1px solid black">' 368 +SELECT geopoly_svg(_shape, 369 + printf('style="fill:none;stroke:%s;stroke-width:1"',clr) 370 + ) 371 + FROM geo1; 372 +SELECT geopoly_svg(poly, 373 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 374 + ) 375 + FROM querypoly; 376 +.print '</svg>' 377 + 378 +.print '<h1>Overlap Query</h1>' 379 +.print '<pre>' 380 +.print 'SELECT *' 381 +.print ' FROM geo1, querypoly' 382 +.print ' WHERE geopoly_overlap(_shape, poly);' 383 +.print 384 +EXPLAIN QUERY PLAN 385 +SELECT geopoly_svg(_shape, 386 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 387 + ) 388 + FROM geo1, querypoly 389 + WHERE geopoly_overlap(_shape, poly); 390 +.print '</pre>' 391 +.print '<svg width="1000" height="800" style="border:1px solid black">' 392 +SELECT geopoly_svg(_shape, 393 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 394 + ) 395 + FROM geo1, querypoly 396 + WHERE geopoly_overlap(_shape, poly); 397 +SELECT geopoly_svg(poly, 398 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 399 + ) 400 + FROM querypoly; 401 +.print '</svg>' 402 + 403 +.print '<h1>Overlap Query And Result Bounding Box</h1>' 404 +.print '<svg width="1000" height="800" style="border:1px solid black">' 405 +SELECT geopoly_svg(_shape, 406 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 407 + ) 408 + FROM geo1, querypoly 409 + WHERE geopoly_overlap(_shape, poly); 410 +SELECT geopoly_svg(geopoly_bbox(poly), 411 + 'style="fill:none;stroke:black;stroke-width:3"' 412 + ) 413 + FROM querypoly; 414 +SELECT geopoly_svg(poly, 415 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 416 + ) 417 + FROM querypoly; 418 +SELECT geopoly_svg(geopoly_group_bbox(_shape), 419 + 'style="fill:none;stroke:red;stroke-width:3"' 420 + ) 421 + FROM geo1, querypoly 422 + WHERE geopoly_overlap(_shape, poly); 423 +.print '</svg>' 424 + 425 +.print '<h1>Bounding-Box Overlap Query</h1>' 426 +.print '<svg width="1000" height="800" style="border:1px solid black">' 427 +SELECT geopoly_svg(_shape, 428 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 429 + ), 430 + geopoly_svg(geopoly_bbox(_shape), 431 + 'style="fill:none;stroke:black;stroke-width:1"' 432 + ) 433 + FROM geo1, querypoly 434 + WHERE geopoly_overlap(geopoly_bbox(_shape), geopoly_bbox(poly)); 435 +SELECT geopoly_svg(poly, 436 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 437 + ) 438 + FROM querypoly; 439 +SELECT geopoly_svg(geopoly_bbox(poly), 440 + 'style="fill:none;stroke:black;stroke-width:3"' 441 + ) 442 + FROM querypoly; 443 +.print '</svg>' 444 + 445 +.print '<h1>Within Query</h1>' 446 +.print '<pre>' 447 +.print 'SELECT *' 448 +.print ' FROM geo1, querypoly' 449 +.print ' WHERE geopoly_within(_shape, poly);' 450 +.print 451 +EXPLAIN QUERY PLAN 452 +SELECT geopoly_svg(_shape, 453 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 454 + ) 455 + FROM geo1, querypoly 456 + WHERE geopoly_within(_shape, poly); 457 +.print '</pre>' 458 +.print '<svg width="1000" height="800" style="border:1px solid black">' 459 +SELECT geopoly_svg(_shape, 460 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 461 + ) 462 + FROM geo1, querypoly 463 + WHERE geopoly_within(_shape, poly); 464 +SELECT geopoly_svg(poly, 465 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 466 + ) 467 + FROM querypoly; 468 +.print '</svg>' 469 + 470 +.print '<h1>Bounding-Box WITHIN Query</h1>' 471 +.print '<svg width="1000" height="800" style="border:1px solid black">' 472 +SELECT geopoly_svg(_shape, 473 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 474 + ), 475 + geopoly_svg(geopoly_bbox(_shape), 476 + 'style="fill:none;stroke:black;stroke-width:1"' 477 + ) 478 + FROM geo1, querypoly 479 + WHERE geopoly_within(geopoly_bbox(_shape), geopoly_bbox(poly)); 480 +SELECT geopoly_svg(poly, 481 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 482 + ) 483 + FROM querypoly; 484 +SELECT geopoly_svg(geopoly_bbox(poly), 485 + 'style="fill:none;stroke:black;stroke-width:3"' 486 + ) 487 + FROM querypoly; 488 +.print '</svg>' 489 + 490 +.print '<h1>Not Overlap Query</h1>' 491 +.print '<pre>' 492 +.print 'SELECT *' 493 +.print ' FROM geo1, querypoly' 494 +.print ' WHERE NOT geopoly_overlap(_shape, poly);' 495 +.print 496 +EXPLAIN QUERY PLAN 497 +SELECT geopoly_svg(_shape, 498 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 499 + ) 500 + FROM geo1, querypoly 501 + WHERE NOT geopoly_overlap(_shape, poly); 502 +.print '</pre>' 503 +.print '<svg width="1000" height="800" style="border:1px solid black">' 504 +SELECT geopoly_svg(_shape, 505 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 506 + ) 507 + FROM geo1, querypoly 508 + WHERE NOT geopoly_overlap(_shape, poly); 509 +SELECT geopoly_svg(poly, 510 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 511 + ) 512 + FROM querypoly; 513 +.print '</svg>' 514 + 515 +.print '<h1>Not Within Query</h1>' 516 +.print '<pre>' 517 +.print 'SELECT *' 518 +.print ' FROM geo1, querypoly' 519 +.print ' WHERE NOT geopoly_within(_shape, poly);' 520 +.print 521 +EXPLAIN QUERY PLAN 522 +SELECT geopoly_svg(_shape, 523 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 524 + ) 525 + FROM geo1, querypoly 526 + WHERE NOT geopoly_within(_shape, poly); 527 +.print '</pre>' 528 +.print '<svg width="1000" height="800" style="border:1px solid black">' 529 +SELECT geopoly_svg(_shape, 530 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 531 + ) 532 + FROM geo1, querypoly 533 + WHERE NOT geopoly_within(_shape, poly); 534 +SELECT geopoly_svg(poly, 535 + printf('style="fill:%s;fill-opacity:0.5;"',clr) 536 + ) 537 + FROM querypoly; 538 +.print '</svg>' 539 + 540 +.print '<h1>Color-Change For Overlapping Elements</h1>' 541 +BEGIN; 542 +UPDATE geo1 543 + SET clr=CASE WHEN rowid IN (SELECT geo1.rowid FROM geo1, querypoly 544 + WHERE geopoly_overlap(_shape,poly)) 545 + THEN 'red' ELSE 'blue' END; 546 +.print '<svg width="1000" height="800" style="border:1px solid black">' 547 +SELECT geopoly_svg(_shape, 548 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 549 + ) 550 + FROM geo1; 551 +SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"') 552 + FROM querypoly; 553 +ROLLBACK; 554 +.print '</svg>' 555 + 556 +.print '<h1>Color-Change And Move Overlapping Elements</h1>' 557 +BEGIN; 558 +UPDATE geo1 559 + SET clr=CASE WHEN rowid IN (SELECT geo1.rowid FROM geo1, querypoly 560 + WHERE geopoly_overlap(_shape,poly)) 561 + THEN 'red' ELSE '#76ccff' END; 562 +UPDATE geo1 563 + SET _shape=geopoly_xform(_shape,1,0,0,1,300,0) 564 + WHERE geopoly_overlap(_shape,(SELECT poly FROM querypoly)); 565 +.print '<svg width="1000" height="800" style="border:1px solid black">' 566 +SELECT geopoly_svg(_shape, 567 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 568 + ) 569 + FROM geo1; 570 +SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"') 571 + FROM querypoly; 572 +--ROLLBACK; 573 +.print '</svg>' 574 + 575 + 576 +.print '<h1>Overlap With Translated Query Polygon</h1>' 577 +UPDATE querypoly SET poly=geopoly_xform(poly,1,0,0,1,300,0); 578 +.print '<svg width="1000" height="800" style="border:1px solid black">' 579 +SELECT geopoly_svg(_shape, 580 + printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr) 581 + ) 582 + FROM geo1 583 + WHERE geopoly_overlap(_shape,(SELECT poly FROM querypoly)); 584 +SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"') 585 + FROM querypoly; 586 +ROLLBACK; 587 +.print '</svg>' 588 + 589 +.print '</html>'
Changes to main.mk.
225 225 $(TOP)/ext/fts3/fts3_write.c 226 226 SRC += \ 227 227 $(TOP)/ext/icu/sqliteicu.h \ 228 228 $(TOP)/ext/icu/icu.c 229 229 SRC += \ 230 230 $(TOP)/ext/rtree/sqlite3rtree.h \ 231 231 $(TOP)/ext/rtree/rtree.h \ 232 - $(TOP)/ext/rtree/rtree.c 232 + $(TOP)/ext/rtree/rtree.c \ 233 + $(TOP)/ext/rtree/geopoly.c 233 234 SRC += \ 234 235 $(TOP)/ext/session/sqlite3session.c \ 235 236 $(TOP)/ext/session/sqlite3session.h 236 237 SRC += \ 237 238 $(TOP)/ext/userauth/userauth.c \ 238 239 $(TOP)/ext/userauth/sqlite3userauth.h 239 240 SRC += \ ................................................................................ 471 472 $(TOP)/ext/fts2/fts2_tokenizer.h 472 473 EXTHDR += \ 473 474 $(TOP)/ext/fts3/fts3.h \ 474 475 $(TOP)/ext/fts3/fts3Int.h \ 475 476 $(TOP)/ext/fts3/fts3_hash.h \ 476 477 $(TOP)/ext/fts3/fts3_tokenizer.h 477 478 EXTHDR += \ 478 - $(TOP)/ext/rtree/rtree.h 479 + $(TOP)/ext/rtree/rtree.h \ 480 + $(TOP)/ext/rtree/geopoly.c 479 481 EXTHDR += \ 480 482 $(TOP)/ext/icu/sqliteicu.h 481 483 EXTHDR += \ 482 484 $(TOP)/ext/fts5/fts5Int.h \ 483 485 fts5parse.h \ 484 486 $(TOP)/ext/fts5/fts5.h 485 487 EXTHDR += \
Changes to src/alter.c.
16 16 17 17 /* 18 18 ** The code in this file only exists if we are not omitting the 19 19 ** ALTER TABLE logic from the build. 20 20 */ 21 21 #ifndef SQLITE_OMIT_ALTERTABLE 22 22 23 - 24 -/* 25 -** This function is used by SQL generated to implement the 26 -** ALTER TABLE command. The first argument is the text of a CREATE TABLE or 27 -** CREATE INDEX command. The second is a table name. The table name in 28 -** the CREATE TABLE or CREATE INDEX statement is replaced with the third 29 -** argument and the result returned. Examples: 30 -** 31 -** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') 32 -** -> 'CREATE TABLE def(a, b, c)' 33 -** 34 -** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') 35 -** -> 'CREATE INDEX i ON def(a, b, c)' 36 -*/ 37 -static void renameTableFunc( 38 - sqlite3_context *context, 39 - int NotUsed, 40 - sqlite3_value **argv 41 -){ 42 - unsigned char const *zSql = sqlite3_value_text(argv[0]); 43 - unsigned char const *zTableName = sqlite3_value_text(argv[1]); 44 - 45 - int token; 46 - Token tname; 47 - unsigned char const *zCsr = zSql; 48 - int len = 0; 49 - char *zRet; 50 - 51 - sqlite3 *db = sqlite3_context_db_handle(context); 52 - 53 - UNUSED_PARAMETER(NotUsed); 54 - 55 - /* The principle used to locate the table name in the CREATE TABLE 56 - ** statement is that the table name is the first non-space token that 57 - ** is immediately followed by a TK_LP or TK_USING token. 58 - */ 59 - if( zSql ){ 60 - do { 61 - if( !*zCsr ){ 62 - /* Ran out of input before finding an opening bracket. Return NULL. */ 63 - return; 64 - } 65 - 66 - /* Store the token that zCsr points to in tname. */ 67 - tname.z = (char*)zCsr; 68 - tname.n = len; 69 - 70 - /* Advance zCsr to the next token. Store that token type in 'token', 71 - ** and its length in 'len' (to be used next iteration of this loop). 72 - */ 73 - do { 74 - zCsr += len; 75 - len = sqlite3GetToken(zCsr, &token); 76 - } while( token==TK_SPACE ); 77 - assert( len>0 || !*zCsr ); 78 - } while( token!=TK_LP && token!=TK_USING ); 79 - 80 - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), 81 - zSql, zTableName, tname.z+tname.n); 82 - sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); 83 - } 84 -} 85 - 86 -/* 87 -** This C function implements an SQL user function that is used by SQL code 88 -** generated by the ALTER TABLE ... RENAME command to modify the definition 89 -** of any foreign key constraints that use the table being renamed as the 90 -** parent table. It is passed three arguments: 91 -** 92 -** 1) The complete text of the CREATE TABLE statement being modified, 93 -** 2) The old name of the table being renamed, and 94 -** 3) The new name of the table being renamed. 95 -** 96 -** It returns the new CREATE TABLE statement. For example: 97 -** 98 -** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') 99 -** -> 'CREATE TABLE t1(a REFERENCES t3)' 100 -*/ 101 -#ifndef SQLITE_OMIT_FOREIGN_KEY 102 -static void renameParentFunc( 103 - sqlite3_context *context, 104 - int NotUsed, 105 - sqlite3_value **argv 106 -){ 107 - sqlite3 *db = sqlite3_context_db_handle(context); 108 - char *zOutput = 0; 109 - char *zResult; 110 - unsigned char const *zInput = sqlite3_value_text(argv[0]); 111 - unsigned char const *zOld = sqlite3_value_text(argv[1]); 112 - unsigned char const *zNew = sqlite3_value_text(argv[2]); 113 - 114 - unsigned const char *z; /* Pointer to token */ 115 - int n; /* Length of token z */ 116 - int token; /* Type of token */ 117 - 118 - UNUSED_PARAMETER(NotUsed); 119 - if( zInput==0 || zOld==0 ) return; 120 - for(z=zInput; *z; z=z+n){ 121 - n = sqlite3GetToken(z, &token); 122 - if( token==TK_REFERENCES ){ 123 - char *zParent; 124 - do { 125 - z += n; 126 - n = sqlite3GetToken(z, &token); 127 - }while( token==TK_SPACE ); 128 - 129 - if( token==TK_ILLEGAL ) break; 130 - zParent = sqlite3DbStrNDup(db, (const char *)z, n); 131 - if( zParent==0 ) break; 132 - sqlite3Dequote(zParent); 133 - if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){ 134 - char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", 135 - (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew 136 - ); 137 - sqlite3DbFree(db, zOutput); 138 - zOutput = zOut; 139 - zInput = &z[n]; 140 - } 141 - sqlite3DbFree(db, zParent); 142 - } 143 - } 144 - 145 - zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput); 146 - sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); 147 - sqlite3DbFree(db, zOutput); 148 -} 149 -#endif 150 - 151 -#ifndef SQLITE_OMIT_TRIGGER 152 -/* This function is used by SQL generated to implement the 153 -** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER 154 -** statement. The second is a table name. The table name in the CREATE 155 -** TRIGGER statement is replaced with the third argument and the result 156 -** returned. This is analagous to renameTableFunc() above, except for CREATE 157 -** TRIGGER, not CREATE INDEX and CREATE TABLE. 158 -*/ 159 -static void renameTriggerFunc( 160 - sqlite3_context *context, 161 - int NotUsed, 162 - sqlite3_value **argv 163 -){ 164 - unsigned char const *zSql = sqlite3_value_text(argv[0]); 165 - unsigned char const *zTableName = sqlite3_value_text(argv[1]); 166 - 167 - int token; 168 - Token tname; 169 - int dist = 3; 170 - unsigned char const *zCsr = zSql; 171 - int len = 0; 172 - char *zRet; 173 - sqlite3 *db = sqlite3_context_db_handle(context); 174 - 175 - UNUSED_PARAMETER(NotUsed); 176 - 177 - /* The principle used to locate the table name in the CREATE TRIGGER 178 - ** statement is that the table name is the first token that is immediately 179 - ** preceded by either TK_ON or TK_DOT and immediately followed by one 180 - ** of TK_WHEN, TK_BEGIN or TK_FOR. 181 - */ 182 - if( zSql ){ 183 - do { 184 - 185 - if( !*zCsr ){ 186 - /* Ran out of input before finding the table name. Return NULL. */ 187 - return; 188 - } 189 - 190 - /* Store the token that zCsr points to in tname. */ 191 - tname.z = (char*)zCsr; 192 - tname.n = len; 193 - 194 - /* Advance zCsr to the next token. Store that token type in 'token', 195 - ** and its length in 'len' (to be used next iteration of this loop). 196 - */ 197 - do { 198 - zCsr += len; 199 - len = sqlite3GetToken(zCsr, &token); 200 - }while( token==TK_SPACE ); 201 - assert( len>0 || !*zCsr ); 202 - 203 - /* Variable 'dist' stores the number of tokens read since the most 204 - ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN 205 - ** token is read and 'dist' equals 2, the condition stated above 206 - ** to be met. 207 - ** 208 - ** Note that ON cannot be a database, table or column name, so 209 - ** there is no need to worry about syntax like 210 - ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. 211 - */ 212 - dist++; 213 - if( token==TK_DOT || token==TK_ON ){ 214 - dist = 0; 215 - } 216 - } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); 217 - 218 - /* Variable tname now contains the token that is the old table-name 219 - ** in the CREATE TRIGGER statement. 220 - */ 221 - zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql), 222 - zSql, zTableName, tname.z+tname.n); 223 - sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); 224 - } 225 -} 226 -#endif /* !SQLITE_OMIT_TRIGGER */ 227 - 228 -/* 229 -** This function is used to create the text of expressions of the form: 230 -** 231 -** name=<constant1> OR name=<constant2> OR ... 232 -** 233 -** If argument zWhere is NULL, then a pointer string containing the text 234 -** "name=<constant>" is returned, where <constant> is the quoted version 235 -** of the string passed as argument zConstant. The returned buffer is 236 -** allocated using sqlite3DbMalloc(). It is the responsibility of the 237 -** caller to ensure that it is eventually freed. 238 -** 239 -** If argument zWhere is not NULL, then the string returned is 240 -** "<where> OR name=<constant>", where <where> is the contents of zWhere. 241 -** In this case zWhere is passed to sqlite3DbFree() before returning. 242 -** 243 -*/ 244 -static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){ 245 - char *zNew; 246 - if( !zWhere ){ 247 - zNew = sqlite3MPrintf(db, "name=%Q", zConstant); 248 - }else{ 249 - zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant); 250 - sqlite3DbFree(db, zWhere); 251 - } 252 - return zNew; 253 -} 254 - 255 -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) 256 -/* 257 -** Generate the text of a WHERE expression which can be used to select all 258 -** tables that have foreign key constraints that refer to table pTab (i.e. 259 -** constraints for which pTab is the parent table) from the sqlite_master 260 -** table. 261 -*/ 262 -static char *whereForeignKeys(Parse *pParse, Table *pTab){ 263 - FKey *p; 264 - char *zWhere = 0; 265 - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ 266 - zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName); 267 - } 268 - return zWhere; 269 -} 270 -#endif 271 - 272 -/* 273 -** Generate the text of a WHERE expression which can be used to select all 274 -** temporary triggers on table pTab from the sqlite_temp_master table. If 275 -** table pTab has no temporary triggers, or is itself stored in the 276 -** temporary database, NULL is returned. 277 -*/ 278 -static char *whereTempTriggers(Parse *pParse, Table *pTab){ 279 - Trigger *pTrig; 280 - char *zWhere = 0; 281 - const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */ 282 - 283 - /* If the table is not located in the temp-db (in which case NULL is 284 - ** returned, loop through the tables list of triggers. For each trigger 285 - ** that is not part of the temp-db schema, add a clause to the WHERE 286 - ** expression being built up in zWhere. 287 - */ 288 - if( pTab->pSchema!=pTempSchema ){ 289 - sqlite3 *db = pParse->db; 290 - for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ 291 - if( pTrig->pSchema==pTempSchema ){ 292 - zWhere = whereOrName(db, zWhere, pTrig->zName); 293 - } 294 - } 295 - } 296 - if( zWhere ){ 297 - char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere); 298 - sqlite3DbFree(pParse->db, zWhere); 299 - zWhere = zNew; 300 - } 301 - return zWhere; 302 -} 303 - 304 -/* 305 -** Generate code to drop and reload the internal representation of table 306 -** pTab from the database, including triggers and temporary triggers. 307 -** Argument zName is the name of the table in the database schema at 308 -** the time the generated code is executed. This can be different from 309 -** pTab->zName if this function is being called to code part of an 310 -** "ALTER TABLE RENAME TO" statement. 311 -*/ 312 -static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ 313 - Vdbe *v; 314 - char *zWhere; 315 - int iDb; /* Index of database containing pTab */ 316 -#ifndef SQLITE_OMIT_TRIGGER 317 - Trigger *pTrig; 318 -#endif 319 - 320 - v = sqlite3GetVdbe(pParse); 321 - if( NEVER(v==0) ) return; 322 - assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); 323 - iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); 324 - assert( iDb>=0 ); 325 - 326 -#ifndef SQLITE_OMIT_TRIGGER 327 - /* Drop any table triggers from the internal schema. */ 328 - for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){ 329 - int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); 330 - assert( iTrigDb==iDb || iTrigDb==1 ); 331 - sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0); 332 - } 333 -#endif 334 - 335 - /* Drop the table and index from the internal schema. */ 336 - sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); 337 - 338 - /* Reload the table, index and permanent trigger schemas. */ 339 - zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); 340 - if( !zWhere ) return; 341 - sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); 342 - 343 -#ifndef SQLITE_OMIT_TRIGGER 344 - /* Now, if the table is not stored in the temp database, reload any temp 345 - ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. 346 - */ 347 - if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ 348 - sqlite3VdbeAddParseSchemaOp(v, 1, zWhere); 349 - } 350 -#endif 351 -} 352 - 353 23 /* 354 24 ** Parameter zName is the name of a table that is about to be altered 355 25 ** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN). 356 26 ** If the table is a system table, this function leaves an error message 357 27 ** in pParse->zErr (system tables may not be altered) and returns non-zero. 358 28 ** 359 29 ** Or, if zName is not a system table, zero is returned. ................................................................................ 361 31 static int isSystemTable(Parse *pParse, const char *zName){ 362 32 if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ 363 33 sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); 364 34 return 1; 365 35 } 366 36 return 0; 367 37 } 38 + 39 +/* 40 +** Generate code to verify that the schemas of database zDb and, if 41 +** bTemp is not true, database "temp", can still be parsed. This is 42 +** called at the end of the generation of an ALTER TABLE ... RENAME ... 43 +** statement to ensure that the operation has not rendered any schema 44 +** objects unusable. 45 +*/ 46 +void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){ 47 + sqlite3NestedParse(pParse, 48 + "SELECT 1 " 49 + "FROM \"%w\".%s " 50 + "WHERE name NOT LIKE 'sqlite_%%'" 51 + " AND sql NOT LIKE 'create virtual%%'" 52 + " AND sqlite_rename_test(%Q, sql, type, name, %d)=0 ", 53 + zDb, MASTER_NAME, 54 + zDb, bTemp 55 + ); 56 + 57 + if( bTemp==0 ){ 58 + sqlite3NestedParse(pParse, 59 + "SELECT 1 " 60 + "FROM temp.%s " 61 + "WHERE name NOT LIKE 'sqlite_%%'" 62 + " AND sql NOT LIKE 'create virtual%%'" 63 + " AND sqlite_rename_test(%Q, sql, type, name, 1)=0 ", 64 + MASTER_NAME, zDb 65 + ); 66 + } 67 +} 68 + 69 +/* 70 +** Generate code to reload the schema for database iDb. And, if iDb!=1, for 71 +** the temp database as well. 72 +*/ 73 +void renameReloadSchema(Parse *pParse, int iDb){ 74 + Vdbe *v = pParse->pVdbe; 75 + if( v ){ 76 + sqlite3ChangeCookie(pParse, iDb); 77 + sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0); 78 + if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0); 79 + } 80 +} 368 81 369 82 /* 370 83 ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" 371 84 ** command. 372 85 */ 373 86 void sqlite3AlterRenameTable( 374 87 Parse *pParse, /* Parser context. */ ................................................................................ 379 92 char *zDb; /* Name of database iDb */ 380 93 Table *pTab; /* Table being renamed */ 381 94 char *zName = 0; /* NULL-terminated version of pName */ 382 95 sqlite3 *db = pParse->db; /* Database connection */ 383 96 int nTabName; /* Number of UTF-8 characters in zTabName */ 384 97 const char *zTabName; /* Original name of the table */ 385 98 Vdbe *v; 386 -#ifndef SQLITE_OMIT_TRIGGER 387 - char *zWhere = 0; /* Where clause to locate temp triggers */ 388 -#endif 389 99 VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */ 390 100 u32 savedDbFlags; /* Saved value of db->mDbFlags */ 391 101 392 102 savedDbFlags = db->mDbFlags; 393 103 if( NEVER(db->mallocFailed) ) goto exit_rename_table; 394 104 assert( pSrc->nSrc==1 ); 395 105 assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); ................................................................................ 454 164 ** schema). Open a statement transaction if the table is a virtual 455 165 ** table. 456 166 */ 457 167 v = sqlite3GetVdbe(pParse); 458 168 if( v==0 ){ 459 169 goto exit_rename_table; 460 170 } 461 - sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb); 462 - sqlite3ChangeCookie(pParse, iDb); 463 171 464 172 /* If this is a virtual table, invoke the xRename() function if 465 173 ** one is defined. The xRename() callback will modify the names 466 174 ** of any resources used by the v-table implementation (including other 467 175 ** SQLite tables) that are identified by the name of the virtual table. 468 176 */ 469 177 #ifndef SQLITE_OMIT_VIRTUALTABLE ................................................................................ 475 183 } 476 184 #endif 477 185 478 186 /* figure out how many UTF-8 characters are in zName */ 479 187 zTabName = pTab->zName; 480 188 nTabName = sqlite3Utf8CharLen(zTabName, -1); 481 189 482 -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) 483 - if( db->flags&SQLITE_ForeignKeys ){ 484 - /* If foreign-key support is enabled, rewrite the CREATE TABLE 485 - ** statements corresponding to all child tables of foreign key constraints 486 - ** for which the renamed table is the parent table. */ 487 - if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){ 488 - sqlite3NestedParse(pParse, 489 - "UPDATE \"%w\".%s SET " 490 - "sql = sqlite_rename_parent(sql, %Q, %Q) " 491 - "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere); 492 - sqlite3DbFree(db, zWhere); 493 - } 494 - } 495 -#endif 190 + /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in 191 + ** the schema to use the new table name. */ 192 + sqlite3NestedParse(pParse, 193 + "UPDATE \"%w\".%s SET " 194 + "sql = sqlite_rename_table(%Q, sql, %Q, %Q, %d) " 195 + "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)" 196 + "AND name NOT LIKE 'sqlite_%%'" 197 + , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName 198 + ); 496 199 497 - /* Modify the sqlite_master table to use the new table name. */ 200 + /* Update the tbl_name and name columns of the sqlite_master table 201 + ** as required. */ 498 202 sqlite3NestedParse(pParse, 499 203 "UPDATE %Q.%s SET " 500 -#ifdef SQLITE_OMIT_TRIGGER 501 - "sql = sqlite_rename_table(sql, %Q), " 502 -#else 503 - "sql = CASE " 504 - "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" 505 - "ELSE sqlite_rename_table(sql, %Q) END, " 506 -#endif 507 204 "tbl_name = %Q, " 508 205 "name = CASE " 509 206 "WHEN type='table' THEN %Q " 510 207 "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " 511 208 "'sqlite_autoindex_' || %Q || substr(name,%d+18) " 512 209 "ELSE name END " 513 210 "WHERE tbl_name=%Q COLLATE nocase AND " 514 211 "(type='table' OR type='index' OR type='trigger');", 515 - zDb, MASTER_NAME, zName, zName, zName, 516 -#ifndef SQLITE_OMIT_TRIGGER 517 - zName, 518 -#endif 519 - zName, nTabName, zTabName 212 + zDb, MASTER_NAME, 213 + zName, zName, zName, 214 + nTabName, zTabName 520 215 ); 521 216 522 217 #ifndef SQLITE_OMIT_AUTOINCREMENT 523 218 /* If the sqlite_sequence table exists in this database, then update 524 219 ** it with the new table name. 525 220 */ 526 221 if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ 527 222 sqlite3NestedParse(pParse, 528 223 "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q", 529 224 zDb, zName, pTab->zName); 530 225 } 531 226 #endif 532 227 533 -#ifndef SQLITE_OMIT_TRIGGER 534 - /* If there are TEMP triggers on this table, modify the sqlite_temp_master 535 - ** table. Don't do this if the table being ALTERed is itself located in 536 - ** the temp database. 537 - */ 538 - if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ 228 + /* If the table being renamed is not itself part of the temp database, 229 + ** edit view and trigger definitions within the temp database 230 + ** as required. */ 231 + if( iDb!=1 ){ 539 232 sqlite3NestedParse(pParse, 540 233 "UPDATE sqlite_temp_master SET " 541 - "sql = sqlite_rename_trigger(sql, %Q), " 542 - "tbl_name = %Q " 543 - "WHERE %s;", zName, zName, zWhere); 544 - sqlite3DbFree(db, zWhere); 234 + "sql = sqlite_rename_table(%Q, sql, %Q, %Q, 1), " 235 + "tbl_name = " 236 + "CASE WHEN tbl_name=%Q COLLATE nocase THEN %Q ELSE tbl_name END " 237 + "WHERE type IN ('view', 'trigger')" 238 + , zDb, zTabName, zName, zTabName, zTabName, zName); 545 239 } 546 -#endif 547 240 548 -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) 549 - if( db->flags&SQLITE_ForeignKeys ){ 550 - FKey *p; 551 - for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){ 552 - Table *pFrom = p->pFrom; 553 - if( pFrom!=pTab ){ 554 - reloadTableSchema(pParse, p->pFrom, pFrom->zName); 555 - } 556 - } 557 - } 558 -#endif 559 - 560 - /* Drop and reload the internal table schema. */ 561 - reloadTableSchema(pParse, pTab, zName); 241 + renameReloadSchema(pParse, iDb); 242 + renameTestSchema(pParse, zDb, iDb==1); 562 243 563 244 exit_rename_table: 564 245 sqlite3SrcListDelete(db, pSrc); 565 246 sqlite3DbFree(db, zName); 566 247 db->mDbFlags = savedDbFlags; 567 248 } 568 249 ................................................................................ 580 261 int iDb; /* Database number */ 581 262 const char *zDb; /* Database name */ 582 263 const char *zTab; /* Table name */ 583 264 char *zCol; /* Null-terminated column definition */ 584 265 Column *pCol; /* The new column */ 585 266 Expr *pDflt; /* Default value for the new column */ 586 267 sqlite3 *db; /* The database connection; */ 587 - Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */ 268 + Vdbe *v; /* The prepared statement under construction */ 588 269 int r1; /* Temporary registers */ 270 + char *zWhere; /* WHERE clause for reloading schema */ 589 271 590 272 db = pParse->db; 591 273 if( pParse->nErr || db->mallocFailed ) return; 592 - assert( v!=0 ); 593 274 pNew = pParse->pNewTable; 594 275 assert( pNew ); 595 276 596 277 assert( sqlite3BtreeHoldsAllMutexes(db) ); 597 278 iDb = sqlite3SchemaToIndex(db, pNew->pSchema); 598 279 zDb = db->aDb[iDb].zDbSName; 599 280 zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ ................................................................................ 680 361 db->mDbFlags = savedDbFlags; 681 362 } 682 363 683 364 /* Make sure the schema version is at least 3. But do not upgrade 684 365 ** from less than 3 to 4, as that will corrupt any preexisting DESC 685 366 ** index. 686 367 */ 687 - r1 = sqlite3GetTempReg(pParse); 688 - sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); 689 - sqlite3VdbeUsesBtree(v, iDb); 690 - sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); 691 - sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); 692 - VdbeCoverage(v); 693 - sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); 694 - sqlite3ReleaseTempReg(pParse, r1); 368 + v = sqlite3GetVdbe(pParse); 369 + if( v ){ 370 + r1 = sqlite3GetTempReg(pParse); 371 + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT); 372 + sqlite3VdbeUsesBtree(v, iDb); 373 + sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2); 374 + sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2); 375 + VdbeCoverage(v); 376 + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3); 377 + sqlite3ReleaseTempReg(pParse, r1); 378 + } 695 379 696 - /* Reload the schema of the modified table. */ 697 - reloadTableSchema(pParse, pTab, pTab->zName); 380 + /* Reload the table definition */ 381 + renameReloadSchema(pParse, iDb); 698 382 } 699 383 700 384 /* 701 385 ** This function is called by the parser after the table-name in 702 386 ** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument 703 387 ** pSrc is the full-name of the table being altered. 704 388 ** ................................................................................ 775 459 pCol->zColl = 0; 776 460 pCol->pDflt = 0; 777 461 } 778 462 pNew->pSchema = db->aDb[iDb].pSchema; 779 463 pNew->addColOffset = pTab->addColOffset; 780 464 pNew->nTabRef = 1; 781 465 782 - /* Begin a transaction and increment the schema cookie. */ 783 - sqlite3BeginWriteOperation(pParse, 0, iDb); 784 - v = sqlite3GetVdbe(pParse); 785 - if( !v ) goto exit_begin_add_column; 786 - sqlite3ChangeCookie(pParse, iDb); 787 - 788 466 exit_begin_add_column: 789 467 sqlite3SrcListDelete(db, pSrc); 790 468 return; 791 469 } 792 470 793 471 /* 794 472 ** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN ................................................................................ 889 567 "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" 890 568 " AND sql NOT LIKE 'create virtual%%'", 891 569 zDb, MASTER_NAME, 892 570 zDb, pTab->zName, iCol, zNew, bQuote, 893 571 pTab->zName 894 572 ); 895 573 896 - /* Drop and reload the database schema. */ 897 - if( pParse->pVdbe ){ 898 - sqlite3ChangeCookie(pParse, iSchema); 899 - sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0); 900 - } 901 - 902 574 sqlite3NestedParse(pParse, 903 - "SELECT 1 " 904 - "FROM \"%w\".%s " 905 - "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)" 906 - " AND sql NOT LIKE 'create virtual%%'" 907 - " AND sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, -1)=0 ", 908 - zDb, MASTER_NAME, 909 - pTab->zName, 910 - zDb, pTab->zName, iCol, zNew 575 + "UPDATE temp.%s SET " 576 + "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d) " 577 + "WHERE type IN ('trigger', 'view')", 578 + MASTER_NAME, 579 + zDb, pTab->zName, iCol, zNew, bQuote 911 580 ); 581 + 582 + /* Drop and reload the database schema. */ 583 + renameReloadSchema(pParse, iSchema); 584 + renameTestSchema(pParse, zDb, iSchema==1); 912 585 913 586 exit_rename_column: 914 587 sqlite3SrcListDelete(db, pSrc); 915 588 sqlite3DbFree(db, zOld); 916 589 sqlite3DbFree(db, zNew); 917 590 return; 918 591 } ................................................................................ 948 621 struct RenameCtx { 949 622 RenameToken *pList; /* List of tokens to overwrite */ 950 623 int nList; /* Number of tokens in pList */ 951 624 int iCol; /* Index of column being renamed */ 952 625 Table *pTab; /* Table being ALTERed */ 953 626 const char *zOld; /* Old column name */ 954 627 }; 628 + 629 +void renameTokenClear(Parse *pParse, void *pPtr){ 630 + RenameToken *p; 631 + assert( pPtr || pParse->db->mallocFailed ); 632 + for(p=pParse->pRename; p; p=p->pNext){ 633 + if( p->p==pPtr ){ 634 + p->p = 0; 635 + } 636 + } 637 +} 955 638 956 639 /* 957 640 ** Add a new RenameToken object mapping parse tree element pPtr into 958 641 ** token *pToken to the Parse object currently under construction. 959 642 ** 960 643 ** Return a copy of pPtr. 961 644 */ 962 645 void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ 963 646 RenameToken *pNew; 647 + assert( pPtr || pParse->db->mallocFailed ); 648 + 649 + renameTokenClear(pParse, pPtr); 964 650 pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken)); 965 651 if( pNew ){ 966 652 pNew->p = pPtr; 967 653 pNew->t = *pToken; 968 654 pNew->pNext = pParse->pRename; 969 655 pParse->pRename = pNew; 970 656 } 657 + 971 658 return pPtr; 972 659 } 973 660 974 661 /* 975 662 ** It is assumed that there is already a RenameToken object associated 976 663 ** with parse tree element pFrom. This function remaps the associated token 977 664 ** to parse tree element pTo. 978 665 */ 979 666 void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){ 980 667 RenameToken *p; 981 - for(p=pParse->pRename; ALWAYS(p); p=p->pNext){ 668 + if( pTo ) renameTokenClear(pParse, pTo); 669 + for(p=pParse->pRename; p; p=p->pNext){ 982 670 if( p->p==pFrom ){ 983 671 p->p = pTo; 984 672 break; 985 673 } 986 674 } 987 - assert( pTo==0 || p ); 988 675 } 989 676 990 677 /* 991 678 ** Free the list of RenameToken objects given in the second argument 992 679 */ 993 680 static void renameTokenFree(sqlite3 *db, RenameToken *pToken){ 994 681 RenameToken *pNext; ................................................................................ 1145 832 char *zName = pIdList->a[i].zName; 1146 833 if( 0==sqlite3_stricmp(zName, zOld) ){ 1147 834 renameTokenFind(pParse, pCtx, (void*)zName); 1148 835 } 1149 836 } 1150 837 } 1151 838 } 839 + 840 +static int renameParseSql( 841 + Parse *p, 842 + const char *zDb, 843 + int bTable, 844 + sqlite3 *db, 845 + const char *zSql, 846 + int bTemp 847 +){ 848 + int rc; 849 + char *zErr = 0; 850 + 851 + db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); 852 + 853 + /* Parse the SQL statement passed as the first argument. If no error 854 + ** occurs and the parse does not result in a new table, index or 855 + ** trigger object, the database must be corrupt. */ 856 + memset(p, 0, sizeof(Parse)); 857 + p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN); 858 + p->db = db; 859 + p->nQueryLoop = 1; 860 + rc = sqlite3RunParser(p, zSql, &zErr); 861 + assert( p->zErrMsg==0 ); 862 + assert( rc!=SQLITE_OK || zErr==0 ); 863 + assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 ); 864 + p->zErrMsg = zErr; 865 + if( db->mallocFailed ) rc = SQLITE_NOMEM; 866 + if( rc==SQLITE_OK 867 + && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 868 + ){ 869 + rc = SQLITE_CORRUPT_BKPT; 870 + } 871 + 872 +#ifdef SQLITE_DEBUG 873 + /* Ensure that all mappings in the Parse.pRename list really do map to 874 + ** a part of the input string. */ 875 + if( rc==SQLITE_OK ){ 876 + int nSql = sqlite3Strlen30(zSql); 877 + RenameToken *pToken; 878 + for(pToken=p->pRename; pToken; pToken=pToken->pNext){ 879 + assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); 880 + } 881 + } 882 +#endif 883 + 884 + db->init.iDb = 0; 885 + return rc; 886 +} 887 + 888 +static int renameEditSql( 889 + sqlite3_context *pCtx, /* Return result here */ 890 + RenameCtx *pRename, /* Rename context */ 891 + const char *zSql, /* SQL statement to edit */ 892 + const char *zNew, /* New token text */ 893 + int bQuote /* True to always quote token */ 894 +){ 895 + int nNew = sqlite3Strlen30(zNew); 896 + int nSql = sqlite3Strlen30(zSql); 897 + sqlite3 *db = sqlite3_context_db_handle(pCtx); 898 + int rc = SQLITE_OK; 899 + char *zQuot; 900 + char *zOut; 901 + int nQuot; 902 + 903 + /* Set zQuot to point to a buffer containing a quoted copy of the 904 + ** identifier zNew. If the corresponding identifier in the original 905 + ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to 906 + ** point to zQuot so that all substitutions are made using the 907 + ** quoted version of the new column name. */ 908 + zQuot = sqlite3_mprintf("\"%w\"", zNew); 909 + if( zQuot==0 ){ 910 + return SQLITE_NOMEM; 911 + }else{ 912 + nQuot = sqlite3Strlen30(zQuot); 913 + } 914 + if( bQuote ){ 915 + zNew = zQuot; 916 + nNew = nQuot; 917 + } 918 + 919 + /* At this point pRename->pList contains a list of RenameToken objects 920 + ** corresponding to all tokens in the input SQL that must be replaced 921 + ** with the new column name. All that remains is to construct and 922 + ** return the edited SQL string. */ 923 + assert( nQuot>=nNew ); 924 + zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1); 925 + if( zOut ){ 926 + int nOut = nSql; 927 + memcpy(zOut, zSql, nSql); 928 + while( pRename->pList ){ 929 + int iOff; /* Offset of token to replace in zOut */ 930 + RenameToken *pBest = renameColumnTokenNext(pRename); 931 + 932 + u32 nReplace; 933 + const char *zReplace; 934 + if( sqlite3IsIdChar(*pBest->t.z) ){ 935 + nReplace = nNew; 936 + zReplace = zNew; 937 + }else{ 938 + nReplace = nQuot; 939 + zReplace = zQuot; 940 + } 941 + 942 + iOff = pBest->t.z - zSql; 943 + if( pBest->t.n!=nReplace ){ 944 + memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 945 + nOut - (iOff + pBest->t.n) 946 + ); 947 + nOut += nReplace - pBest->t.n; 948 + zOut[nOut] = '\0'; 949 + } 950 + memcpy(&zOut[iOff], zReplace, nReplace); 951 + sqlite3DbFree(db, pBest); 952 + } 953 + 954 + sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT); 955 + sqlite3DbFree(db, zOut); 956 + }else{ 957 + rc = SQLITE_NOMEM; 958 + } 959 + 960 + sqlite3_free(zQuot); 961 + return rc; 962 +} 963 + 964 +static int renameResolveTrigger( 965 + Parse *pParse, 966 + const char *zDb 967 +){ 968 + sqlite3 *db = pParse->db; 969 + TriggerStep *pStep; 970 + NameContext sNC; 971 + int rc = SQLITE_OK; 972 + 973 + memset(&sNC, 0, sizeof(sNC)); 974 + sNC.pParse = pParse; 975 + pParse->pTriggerTab = sqlite3FindTable(db, pParse->pNewTrigger->table, zDb); 976 + pParse->eTriggerOp = pParse->pNewTrigger->op; 977 + 978 + /* Resolve symbols in WHEN clause */ 979 + if( pParse->pNewTrigger->pWhen ){ 980 + rc = sqlite3ResolveExprNames(&sNC, pParse->pNewTrigger->pWhen); 981 + } 982 + 983 + for(pStep=pParse->pNewTrigger->step_list; 984 + rc==SQLITE_OK && pStep; 985 + pStep=pStep->pNext 986 + ){ 987 + if( pStep->pSelect ){ 988 + sqlite3SelectPrep(pParse, pStep->pSelect, &sNC); 989 + if( pParse->nErr ) rc = pParse->rc; 990 + } 991 + if( rc==SQLITE_OK && pStep->zTarget ){ 992 + Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb); 993 + if( pTarget==0 ){ 994 + rc = SQLITE_ERROR; 995 + }else{ 996 + SrcList sSrc; 997 + memset(&sSrc, 0, sizeof(sSrc)); 998 + sSrc.nSrc = 1; 999 + sSrc.a[0].zName = pStep->zTarget; 1000 + sSrc.a[0].pTab = pTarget; 1001 + sNC.pSrcList = &sSrc; 1002 + if( pStep->pWhere ){ 1003 + rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); 1004 + } 1005 + if( rc==SQLITE_OK ){ 1006 + rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); 1007 + } 1008 + assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); 1009 + if( pStep->pUpsert ){ 1010 + Upsert *pUpsert = pStep->pUpsert; 1011 + assert( rc==SQLITE_OK ); 1012 + pUpsert->pUpsertSrc = &sSrc; 1013 + sNC.uNC.pUpsert = pUpsert; 1014 + sNC.ncFlags = NC_UUpsert; 1015 + rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); 1016 + if( rc==SQLITE_OK ){ 1017 + ExprList *pUpsertSet = pUpsert->pUpsertSet; 1018 + rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); 1019 + } 1020 + if( rc==SQLITE_OK ){ 1021 + rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); 1022 + } 1023 + if( rc==SQLITE_OK ){ 1024 + rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); 1025 + } 1026 + sNC.ncFlags = 0; 1027 + } 1028 + } 1029 + } 1030 + } 1031 + return rc; 1032 +} 1033 + 1034 +static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){ 1035 + TriggerStep *pStep; 1036 + 1037 + /* Find tokens to edit in WHEN clause */ 1038 + sqlite3WalkExpr(pWalker, pTrigger->pWhen); 1039 + 1040 + /* Find tokens to edit in trigger steps */ 1041 + for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ 1042 + sqlite3WalkSelect(pWalker, pStep->pSelect); 1043 + sqlite3WalkExpr(pWalker, pStep->pWhere); 1044 + sqlite3WalkExprList(pWalker, pStep->pExprList); 1045 + if( pStep->pUpsert ){ 1046 + Upsert *pUpsert = pStep->pUpsert; 1047 + sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget); 1048 + sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet); 1049 + sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere); 1050 + sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere); 1051 + } 1052 + } 1053 +} 1054 + 1055 +static void renameParseCleanup(Parse *pParse){ 1056 + sqlite3 *db = pParse->db; 1057 + if( pParse->pVdbe ){ 1058 + sqlite3VdbeFinalize(pParse->pVdbe); 1059 + } 1060 + sqlite3DeleteTable(db, pParse->pNewTable); 1061 + if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex); 1062 + sqlite3DeleteTrigger(db, pParse->pNewTrigger); 1063 + sqlite3DbFree(db, pParse->zErrMsg); 1064 + renameTokenFree(db, pParse->pRename); 1065 + sqlite3ParserReset(pParse); 1066 +} 1152 1067 1153 1068 /* 1154 1069 ** SQL function: 1155 1070 ** 1156 1071 ** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) 1157 1072 ** 1158 1073 ** 0. zSql: SQL statement to rewrite 1159 1074 ** 1. type: Type of object ("table", "view" etc.) 1160 1075 ** 2. object: Name of object 1161 1076 ** 3. Database: Database name (e.g. "main") 1162 1077 ** 4. Table: Table name 1163 1078 ** 5. iCol: Index of column to rename 1164 1079 ** 6. zNew: New column name 1165 -** 7. bQuote: Non-zero if the new column name should be quoted. Negative 1166 -** if this function is being called to check that the schema 1167 -** can still be parsed and symbols resolved after the column 1168 -** has been renamed. 1080 +** 7. bQuote: Non-zero if the new column name should be quoted. 1169 1081 ** 1170 1082 ** Do a column rename operation on the CREATE statement given in zSql. 1171 1083 ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol 1172 1084 ** into zNew. The name should be quoted if bQuote is true. 1173 1085 ** 1174 1086 ** This function is used internally by the ALTER TABLE RENAME COLUMN command. 1175 1087 ** Though accessible to application code, it is not intended for use by ................................................................................ 1194 1106 const char *zDb = (const char*)sqlite3_value_text(argv[3]); 1195 1107 const char *zTable = (const char*)sqlite3_value_text(argv[4]); 1196 1108 int iCol = sqlite3_value_int(argv[5]); 1197 1109 const char *zNew = (const char*)sqlite3_value_text(argv[6]); 1198 1110 int nNew = sqlite3_value_bytes(argv[6]); 1199 1111 int bQuote = sqlite3_value_int(argv[7]); 1200 1112 const char *zOld; 1201 - 1113 + int bTemp = 0; 1202 1114 int rc; 1203 1115 char *zErr = 0; 1204 1116 Parse sParse; 1205 1117 Walker sWalker; 1206 1118 Index *pIdx; 1207 1119 char *zOut = 0; 1208 - 1209 - char *zQuot = 0; /* Quoted version of zNew */ 1210 - int nQuot = 0; /* Length of zQuot in bytes */ 1211 1120 int i; 1212 1121 Table *pTab; 1122 +#ifndef SQLITE_OMIT_AUTHORIZATION 1123 + sqlite3_xauth xAuth = db->xAuth; 1124 +#endif 1213 1125 1214 1126 UNUSED_PARAMETER(NotUsed); 1215 1127 if( zSql==0 ) return; 1216 1128 if( zTable==0 ) return; 1217 1129 if( zNew==0 ) return; 1218 1130 if( iCol<0 ) return; 1219 1131 sqlite3BtreeEnterAll(db); ................................................................................ 1222 1134 sqlite3BtreeLeaveAll(db); 1223 1135 return; 1224 1136 } 1225 1137 zOld = pTab->aCol[iCol].zName; 1226 1138 memset(&sCtx, 0, sizeof(sCtx)); 1227 1139 sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); 1228 1140 1229 - /* Parse the SQL statement passed as the first argument. If no error 1230 - ** occurs and the parse does not result in a new table, index or 1231 - ** trigger object, the database must be corrupt. */ 1232 - memset(&sParse, 0, sizeof(sParse)); 1233 - sParse.eParseMode = PARSE_MODE_RENAME_COLUMN; 1234 - sParse.db = db; 1235 - sParse.nQueryLoop = 1; 1236 - rc = sqlite3RunParser(&sParse, zSql, &zErr); 1237 - assert( sParse.zErrMsg==0 ); 1238 - assert( rc!=SQLITE_OK || zErr==0 ); 1239 - assert( (!!sParse.pNewTable)+(!!sParse.pNewIndex)+(!!sParse.pNewTrigger)<2 ); 1240 - sParse.zErrMsg = zErr; 1241 - if( db->mallocFailed ) rc = SQLITE_NOMEM; 1242 - if( rc==SQLITE_OK 1243 - && sParse.pNewTable==0 && sParse.pNewIndex==0 && sParse.pNewTrigger==0 1244 - ){ 1245 - rc = SQLITE_CORRUPT_BKPT; 1246 - } 1247 - 1248 -#ifdef SQLITE_DEBUG 1249 - /* Ensure that all mappings in the Parse.pRename list really do map to 1250 - ** a part of the input string. */ 1251 - assert( sqlite3Strlen30(zSql)==nSql ); 1252 - if( rc==SQLITE_OK ){ 1253 - RenameToken *pToken; 1254 - for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){ 1255 - assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] ); 1256 - } 1257 - } 1141 +#ifndef SQLITE_OMIT_AUTHORIZATION 1142 + db->xAuth = 0; 1258 1143 #endif 1259 - 1260 - /* Set zQuot to point to a buffer containing a quoted copy of the 1261 - ** identifier zNew. If the corresponding identifier in the original 1262 - ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to 1263 - ** point to zQuot so that all substitutions are made using the 1264 - ** quoted version of the new column name. */ 1265 - if( rc==SQLITE_OK ){ 1266 - zQuot = sqlite3_mprintf("\"%w\"", zNew); 1267 - if( zQuot==0 ){ 1268 - rc = SQLITE_NOMEM; 1269 - }else{ 1270 - nQuot = sqlite3Strlen30(zQuot); 1271 - } 1272 - } 1273 - if( bQuote ){ 1274 - zNew = zQuot; 1275 - nNew = nQuot; 1276 - } 1144 + rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp); 1277 1145 1278 1146 /* Find tokens that need to be replaced. */ 1279 1147 memset(&sWalker, 0, sizeof(Walker)); 1280 1148 sWalker.pParse = &sParse; 1281 1149 sWalker.xExprCallback = renameColumnExprCb; 1282 1150 sWalker.xSelectCallback = renameColumnSelectCb; 1283 1151 sWalker.u.pRename = &sCtx; ................................................................................ 1328 1196 } 1329 1197 }else if( sParse.pNewIndex ){ 1330 1198 sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr); 1331 1199 sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); 1332 1200 }else{ 1333 1201 /* A trigger */ 1334 1202 TriggerStep *pStep; 1335 - NameContext sNC; 1336 - memset(&sNC, 0, sizeof(sNC)); 1337 - sNC.pParse = &sParse; 1338 - sParse.pTriggerTab = sqlite3FindTable(db, sParse.pNewTrigger->table, zDb); 1339 - sParse.eTriggerOp = sParse.pNewTrigger->op; 1203 + rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb)); 1204 + if( rc!=SQLITE_OK ) goto renameColumnFunc_done; 1340 1205 1341 - /* Resolve symbols in WHEN clause */ 1342 - if( sParse.pNewTrigger->pWhen ){ 1343 - rc = sqlite3ResolveExprNames(&sNC, sParse.pNewTrigger->pWhen); 1344 - } 1345 - 1346 - for(pStep=sParse.pNewTrigger->step_list; 1347 - rc==SQLITE_OK && pStep; 1348 - pStep=pStep->pNext 1349 - ){ 1350 - if( pStep->pSelect ){ 1351 - sqlite3SelectPrep(&sParse, pStep->pSelect, &sNC); 1352 - if( sParse.nErr ) rc = sParse.rc; 1353 - } 1354 - if( rc==SQLITE_OK && pStep->zTarget ){ 1206 + for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ 1207 + if( pStep->zTarget ){ 1355 1208 Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb); 1356 - if( pTarget==0 ){ 1357 - rc = SQLITE_ERROR; 1358 - }else{ 1359 - SrcList sSrc; 1360 - memset(&sSrc, 0, sizeof(sSrc)); 1361 - sSrc.nSrc = 1; 1362 - sSrc.a[0].zName = pStep->zTarget; 1363 - sSrc.a[0].pTab = pTarget; 1364 - sNC.pSrcList = &sSrc; 1365 - if( pStep->pWhere ){ 1366 - rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere); 1209 + if( pTarget==pTab ){ 1210 + if( pStep->pUpsert ){ 1211 + ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet; 1212 + renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); 1367 1213 } 1368 - if( rc==SQLITE_OK ){ 1369 - rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList); 1370 - } 1371 - assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) ); 1372 - if( pStep->pUpsert ){ 1373 - Upsert *pUpsert = pStep->pUpsert; 1374 - assert( rc==SQLITE_OK ); 1375 - pUpsert->pUpsertSrc = &sSrc; 1376 - sNC.uNC.pUpsert = pUpsert; 1377 - sNC.ncFlags = NC_UUpsert; 1378 - rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget); 1379 - if( rc==SQLITE_OK ){ 1380 - ExprList *pUpsertSet = pUpsert->pUpsertSet; 1381 - if( pTarget==pTab ){ 1382 - renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld); 1383 - } 1384 - rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet); 1385 - } 1386 - if( rc==SQLITE_OK ){ 1387 - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere); 1388 - } 1389 - if( rc==SQLITE_OK ){ 1390 - rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere); 1391 - } 1392 - sNC.ncFlags = 0; 1393 - } 1394 - 1395 - if( rc==SQLITE_OK && pTarget==pTab ){ 1396 - renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); 1397 - renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); 1398 - } 1214 + renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld); 1215 + renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld); 1399 1216 } 1400 1217 } 1401 1218 } 1402 1219 1403 - if( rc!=SQLITE_OK ) goto renameColumnFunc_done; 1404 1220 1405 1221 /* Find tokens to edit in UPDATE OF clause */ 1406 1222 if( sParse.pTriggerTab==pTab ){ 1407 1223 renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld); 1408 1224 } 1409 1225 1410 - /* Find tokens to edit in WHEN clause */ 1411 - sqlite3WalkExpr(&sWalker, sParse.pNewTrigger->pWhen); 1412 - 1413 - /* Find tokens to edit in trigger steps */ 1414 - for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){ 1415 - sqlite3WalkSelect(&sWalker, pStep->pSelect); 1416 - sqlite3WalkExpr(&sWalker, pStep->pWhere); 1417 - sqlite3WalkExprList(&sWalker, pStep->pExprList); 1418 - if( pStep->pUpsert ){ 1419 - Upsert *pUpsert = pStep->pUpsert; 1420 - sqlite3WalkExprList(&sWalker, pUpsert->pUpsertTarget); 1421 - sqlite3WalkExprList(&sWalker, pUpsert->pUpsertSet); 1422 - sqlite3WalkExpr(&sWalker, pUpsert->pUpsertWhere); 1423 - sqlite3WalkExpr(&sWalker, pUpsert->pUpsertTargetWhere); 1424 - } 1425 - } 1226 + /* Find tokens to edit in various expressions and selects */ 1227 + renameWalkTrigger(&sWalker, sParse.pNewTrigger); 1426 1228 } 1427 1229 1428 - /* At this point sCtx.pList contains a list of RenameToken objects 1429 - ** corresponding to all tokens in the input SQL that must be replaced 1430 - ** with the new column name. All that remains is to construct and 1431 - ** return the edited SQL string. */ 1432 1230 assert( rc==SQLITE_OK ); 1433 - assert( nQuot>=nNew ); 1434 - zOut = sqlite3DbMallocZero(db, nSql + sCtx.nList*nQuot + 1); 1435 - if( zOut ){ 1436 - int nOut = nSql; 1437 - memcpy(zOut, zSql, nSql); 1438 - while( sCtx.pList ){ 1439 - int iOff; /* Offset of token to replace in zOut */ 1440 - RenameToken *pBest = renameColumnTokenNext(&sCtx); 1441 - 1442 - u32 nReplace; 1443 - const char *zReplace; 1444 - if( sqlite3IsIdChar(*pBest->t.z) ){ 1445 - nReplace = nNew; 1446 - zReplace = zNew; 1447 - }else{ 1448 - nReplace = nQuot; 1449 - zReplace = zQuot; 1450 - } 1451 - 1452 - iOff = pBest->t.z - zSql; 1453 - if( pBest->t.n!=nReplace ){ 1454 - memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 1455 - nOut - (iOff + pBest->t.n) 1456 - ); 1457 - nOut += nReplace - pBest->t.n; 1458 - zOut[nOut] = '\0'; 1459 - } 1460 - memcpy(&zOut[iOff], zReplace, nReplace); 1461 - sqlite3DbFree(db, pBest); 1462 - } 1463 - 1464 - sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); 1465 - sqlite3DbFree(db, zOut); 1466 - }else{ 1467 - rc = SQLITE_NOMEM; 1468 - } 1231 + rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote); 1469 1232 1470 1233 renameColumnFunc_done: 1471 1234 if( rc!=SQLITE_OK ){ 1472 1235 if( sParse.zErrMsg ){ 1473 - renameColumnParseError(context, (bQuote<0), argv[1], argv[2], &sParse); 1236 + renameColumnParseError(context, 0, argv[1], argv[2], &sParse); 1474 1237 }else{ 1475 1238 sqlite3_result_error_code(context, rc); 1476 1239 } 1477 1240 } 1478 1241 1479 - if( sParse.pVdbe ){ 1480 - sqlite3VdbeFinalize(sParse.pVdbe); 1481 - } 1482 - sqlite3DeleteTable(db, sParse.pNewTable); 1483 - if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex); 1484 - sqlite3DeleteTrigger(db, sParse.pNewTrigger); 1485 - renameTokenFree(db, sParse.pRename); 1242 + renameParseCleanup(&sParse); 1486 1243 renameTokenFree(db, sCtx.pList); 1487 - sqlite3DbFree(db, sParse.zErrMsg); 1488 - sqlite3ParserReset(&sParse); 1489 - sqlite3_free(zQuot); 1244 +#ifndef SQLITE_OMIT_AUTHORIZATION 1245 + db->xAuth = xAuth; 1246 +#endif 1490 1247 sqlite3BtreeLeaveAll(db); 1491 1248 } 1249 + 1250 +static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ 1251 + RenameCtx *p = pWalker->u.pRename; 1252 + if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){ 1253 + renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab); 1254 + } 1255 + return WRC_Continue; 1256 +} 1257 + 1258 +/* 1259 +** This is a Walker select callback. 1260 +*/ 1261 +static int renameTableSelectCb(Walker *pWalker, Select *pSelect){ 1262 + int i; 1263 + RenameCtx *p = pWalker->u.pRename; 1264 + SrcList *pSrc = pSelect->pSrc; 1265 + for(i=0; i<pSrc->nSrc; i++){ 1266 + struct SrcList_item *pItem = &pSrc->a[i]; 1267 + if( pItem->pTab==p->pTab ){ 1268 + renameTokenFind(pWalker->pParse, p, pItem->zName); 1269 + } 1270 + } 1271 + 1272 + return WRC_Continue; 1273 +} 1274 + 1275 + 1276 +/* 1277 +** This C function implements an SQL user function that is used by SQL code 1278 +** generated by the ALTER TABLE ... RENAME command to modify the definition 1279 +** of any foreign key constraints that use the table being renamed as the 1280 +** parent table. It is passed three arguments: 1281 +** 1282 +** 0: The database containing the table being renamed. 1283 +** 1: The complete text of the schema statement being modified, 1284 +** 2: The old name of the table being renamed, and 1285 +** 3: The new name of the table being renamed. 1286 +** 4: True if the schema statement comes from the temp db. 1287 +** 1288 +** It returns the new schema statement. For example: 1289 +** 1290 +** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0) 1291 +** -> 'CREATE TABLE t1(a REFERENCES t3)' 1292 +*/ 1293 +static void renameTableFunc( 1294 + sqlite3_context *context, 1295 + int NotUsed, 1296 + sqlite3_value **argv 1297 +){ 1298 + sqlite3 *db = sqlite3_context_db_handle(context); 1299 + char *zOutput = 0; 1300 + char *zResult; 1301 + unsigned char const *zDb = sqlite3_value_text(argv[0]); 1302 + unsigned char const *zInput = sqlite3_value_text(argv[1]); 1303 + unsigned char const *zOld = sqlite3_value_text(argv[2]); 1304 + unsigned char const *zNew = sqlite3_value_text(argv[3]); 1305 + int bTemp = sqlite3_value_int(argv[4]); 1306 + 1307 + if( zInput && zOld && zNew ){ 1308 + unsigned const char *z; /* Pointer to token */ 1309 + int n; /* Length of token z */ 1310 + int token; /* Type of token */ 1311 + 1312 + Parse sParse; 1313 + int rc; 1314 + int bQuote = 1; 1315 + RenameCtx sCtx; 1316 + Walker sWalker; 1317 + 1318 +#ifndef SQLITE_OMIT_AUTHORIZATION 1319 + sqlite3_xauth xAuth = db->xAuth; 1320 + db->xAuth = 0; 1321 +#endif 1322 + 1323 + sqlite3BtreeEnterAll(db); 1324 + 1325 + memset(&sCtx, 0, sizeof(RenameCtx)); 1326 + sCtx.pTab = sqlite3FindTable(db, zOld, zDb); 1327 + memset(&sWalker, 0, sizeof(Walker)); 1328 + sWalker.pParse = &sParse; 1329 + sWalker.xExprCallback = renameTableExprCb; 1330 + sWalker.xSelectCallback = renameTableSelectCb; 1331 + sWalker.u.pRename = &sCtx; 1332 + 1333 + rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); 1334 + 1335 + if( rc==SQLITE_OK ){ 1336 + if( sParse.pNewTable ){ 1337 + Table *pTab = sParse.pNewTable; 1338 + 1339 + if( pTab->pSelect ){ 1340 + NameContext sNC; 1341 + memset(&sNC, 0, sizeof(sNC)); 1342 + sNC.pParse = &sParse; 1343 + 1344 + sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC); 1345 + if( sParse.nErr ) rc = sParse.rc; 1346 + sqlite3WalkSelect(&sWalker, pTab->pSelect); 1347 + }else{ 1348 + /* Modify any FK definitions to point to the new table. */ 1349 +#ifndef SQLITE_OMIT_FOREIGN_KEY 1350 + FKey *pFKey; 1351 + for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ 1352 + if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ 1353 + renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo); 1354 + } 1355 + } 1356 +#endif 1357 + 1358 + /* If this is the table being altered, fix any table refs in CHECK 1359 + ** expressions. Also update the name that appears right after the 1360 + ** "CREATE [VIRTUAL] TABLE" bit. */ 1361 + if( sqlite3_stricmp(zOld, pTab->zName)==0 ){ 1362 + sCtx.pTab = pTab; 1363 + sqlite3WalkExprList(&sWalker, pTab->pCheck); 1364 + renameTokenFind(&sParse, &sCtx, pTab->zName); 1365 + } 1366 + } 1367 + } 1368 + 1369 + else if( sParse.pNewIndex ){ 1370 + renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName); 1371 + sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere); 1372 + } 1373 + 1374 +#ifndef SQLITE_OMIT_TRIGGER 1375 + else if( sParse.pNewTrigger ){ 1376 + Trigger *pTrigger = sParse.pNewTrigger; 1377 + TriggerStep *pStep; 1378 + if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld) 1379 + && sCtx.pTab->pSchema==pTrigger->pTabSchema 1380 + ){ 1381 + renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table); 1382 + } 1383 + 1384 + rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); 1385 + if( rc==SQLITE_OK ){ 1386 + renameWalkTrigger(&sWalker, pTrigger); 1387 + for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){ 1388 + if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ 1389 + renameTokenFind(&sParse, &sCtx, pStep->zTarget); 1390 + } 1391 + } 1392 + } 1393 + } 1394 +#endif 1395 + } 1396 + 1397 + if( rc==SQLITE_OK ){ 1398 + rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); 1399 + } 1400 + if( rc!=SQLITE_OK ){ 1401 + sqlite3_result_error_code(context, rc); 1402 + } 1403 + 1404 + renameParseCleanup(&sParse); 1405 + renameTokenFree(db, sCtx.pList); 1406 + sqlite3BtreeLeaveAll(db); 1407 +#ifndef SQLITE_OMIT_AUTHORIZATION 1408 + db->xAuth = xAuth; 1409 +#endif 1410 + } 1411 + 1412 + return; 1413 +} 1414 + 1415 +static void renameTableTest( 1416 + sqlite3_context *context, 1417 + int NotUsed, 1418 + sqlite3_value **argv 1419 +){ 1420 + sqlite3 *db = sqlite3_context_db_handle(context); 1421 + unsigned char const *zDb = sqlite3_value_text(argv[0]); 1422 + unsigned char const *zInput = sqlite3_value_text(argv[1]); 1423 + int bTemp = sqlite3_value_int(argv[4]); 1424 + 1425 +#ifndef SQLITE_OMIT_AUTHORIZATION 1426 + sqlite3_xauth xAuth = db->xAuth; 1427 + db->xAuth = 0; 1428 +#endif 1429 + 1430 + if( zDb && zInput ){ 1431 + int rc; 1432 + Parse sParse; 1433 + rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp); 1434 + if( rc==SQLITE_OK ){ 1435 + if( sParse.pNewTable && sParse.pNewTable->pSelect ){ 1436 + NameContext sNC; 1437 + memset(&sNC, 0, sizeof(sNC)); 1438 + sNC.pParse = &sParse; 1439 + sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC); 1440 + if( sParse.nErr ) rc = sParse.rc; 1441 + } 1442 + 1443 + else if( sParse.pNewTrigger ){ 1444 + rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb); 1445 + } 1446 + } 1447 + 1448 + if( rc!=SQLITE_OK ){ 1449 + renameColumnParseError(context, 1, argv[2], argv[3], &sParse); 1450 + } 1451 + renameParseCleanup(&sParse); 1452 + } 1453 + 1454 +#ifndef SQLITE_OMIT_AUTHORIZATION 1455 + db->xAuth = xAuth; 1456 +#endif 1457 +} 1492 1458 1493 1459 /* 1494 1460 ** Register built-in functions used to help implement ALTER TABLE 1495 1461 */ 1496 1462 void sqlite3AlterFunctions(void){ 1497 1463 static FuncDef aAlterTableFuncs[] = { 1498 - FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc), 1499 1464 FUNCTION(sqlite_rename_column, 8, 0, 0, renameColumnFunc), 1500 -#ifndef SQLITE_OMIT_TRIGGER 1501 - FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc), 1502 -#endif 1503 -#ifndef SQLITE_OMIT_FOREIGN_KEY 1504 - FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc), 1505 -#endif 1465 + FUNCTION(sqlite_rename_table, 5, 0, 0, renameTableFunc), 1466 + FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest), 1506 1467 }; 1507 1468 sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); 1508 1469 } 1509 1470 #endif /* SQLITE_ALTER_TABLE */
Changes to src/build.c.
779 779 *pUnqual = pName2; 780 780 iDb = sqlite3FindDb(db, pName1); 781 781 if( iDb<0 ){ 782 782 sqlite3ErrorMsg(pParse, "unknown database %T", pName1); 783 783 return -1; 784 784 } 785 785 }else{ 786 - assert( db->init.iDb==0 || db->init.busy 786 + assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT 787 787 || (db->mDbFlags & DBFLAG_Vacuum)!=0); 788 788 iDb = db->init.iDb; 789 789 *pUnqual = pName1; 790 790 } 791 791 return iDb; 792 792 } 793 793 ................................................................................ 874 874 /* If creating a temp table, the name may not be qualified. Unless 875 875 ** the database name is "temp" anyway. */ 876 876 sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); 877 877 return; 878 878 } 879 879 if( !OMIT_TEMPDB && isTemp ) iDb = 1; 880 880 zName = sqlite3NameFromToken(db, pName); 881 + if( IN_RENAME_OBJECT ){ 882 + sqlite3RenameTokenMap(pParse, (void*)zName, pName); 883 + } 881 884 } 882 885 pParse->sNameToken = *pName; 883 886 if( zName==0 ) return; 884 887 if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ 885 888 goto begin_table_error; 886 889 } 887 890 if( db->init.iDb==1 ) isTemp = 1; ................................................................................ 1068 1071 if( (p = pParse->pNewTable)==0 ) return; 1069 1072 if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){ 1070 1073 sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); 1071 1074 return; 1072 1075 } 1073 1076 z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2); 1074 1077 if( z==0 ) return; 1075 - if( IN_RENAME_COLUMN ) sqlite3RenameTokenMap(pParse, (void*)z, pName); 1078 + if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName); 1076 1079 memcpy(z, pName->z, pName->n); 1077 1080 z[pName->n] = 0; 1078 1081 sqlite3Dequote(z); 1079 1082 for(i=0; i<p->nCol; i++){ 1080 1083 if( sqlite3_stricmp(z, p->aCol[i].zName)==0 ){ 1081 1084 sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); 1082 1085 sqlite3DbFree(db, z); ................................................................................ 1366 1369 } 1367 1370 } 1368 1371 if( nTerm==1 1369 1372 && pCol 1370 1373 && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0 1371 1374 && sortOrder!=SQLITE_SO_DESC 1372 1375 ){ 1373 - if( IN_RENAME_COLUMN && pList ){ 1376 + if( IN_RENAME_OBJECT && pList ){ 1374 1377 sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr); 1375 1378 } 1376 1379 pTab->iPKey = iCol; 1377 1380 pTab->keyConf = (u8)onError; 1378 1381 assert( autoInc==0 || autoInc==1 ); 1379 1382 pTab->tabFlags |= autoInc*TF_Autoincrement; 1380 1383 if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder; ................................................................................ 2171 2174 if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; 2172 2175 2173 2176 /* Make a copy of the entire SELECT statement that defines the view. 2174 2177 ** This will force all the Expr.token.z values to be dynamically 2175 2178 ** allocated rather than point to the input string - which means that 2176 2179 ** they will persist after the current sqlite3_exec() call returns. 2177 2180 */ 2178 - if( IN_RENAME_COLUMN ){ 2181 + if( IN_RENAME_OBJECT ){ 2179 2182 p->pSelect = pSelect; 2180 2183 pSelect = 0; 2181 2184 }else{ 2182 2185 p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); 2183 2186 } 2184 2187 p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE); 2185 2188 if( db->mallocFailed ) goto create_view_fail; ................................................................................ 2744 2747 if( pFKey==0 ){ 2745 2748 goto fk_end; 2746 2749 } 2747 2750 pFKey->pFrom = p; 2748 2751 pFKey->pNextFrom = p->pFKey; 2749 2752 z = (char*)&pFKey->aCol[nCol]; 2750 2753 pFKey->zTo = z; 2754 + if( IN_RENAME_OBJECT ){ 2755 + sqlite3RenameTokenMap(pParse, (void*)z, pTo); 2756 + } 2751 2757 memcpy(z, pTo->z, pTo->n); 2752 2758 z[pTo->n] = 0; 2753 2759 sqlite3Dequote(z); 2754 2760 z += pTo->n+1; 2755 2761 pFKey->nCol = nCol; 2756 2762 if( pFromCol==0 ){ 2757 2763 pFKey->aCol[0].iFrom = p->nCol-1; ................................................................................ 2766 2772 } 2767 2773 if( j>=p->nCol ){ 2768 2774 sqlite3ErrorMsg(pParse, 2769 2775 "unknown column \"%s\" in foreign key definition", 2770 2776 pFromCol->a[i].zName); 2771 2777 goto fk_end; 2772 2778 } 2773 - if( IN_RENAME_COLUMN ){ 2779 + if( IN_RENAME_OBJECT ){ 2774 2780 sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName); 2775 2781 } 2776 2782 } 2777 2783 } 2778 2784 if( pToCol ){ 2779 2785 for(i=0; i<nCol; i++){ 2780 2786 int n = sqlite3Strlen30(pToCol->a[i].zName); 2781 2787 pFKey->aCol[i].zCol = z; 2782 - if( IN_RENAME_COLUMN ){ 2788 + if( IN_RENAME_OBJECT ){ 2783 2789 sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName); 2784 2790 } 2785 2791 memcpy(z, pToCol->a[i].zName, n); 2786 2792 z[n] = 0; 2787 2793 z += n+1; 2788 2794 } 2789 2795 } ................................................................................ 3110 3116 if( pName ){ 3111 3117 zName = sqlite3NameFromToken(db, pName); 3112 3118 if( zName==0 ) goto exit_create_index; 3113 3119 assert( pName->z!=0 ); 3114 3120 if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ 3115 3121 goto exit_create_index; 3116 3122 } 3117 - if( !IN_RENAME_COLUMN ){ 3123 + if( !IN_RENAME_OBJECT ){ 3118 3124 if( !db->init.busy ){ 3119 3125 if( sqlite3FindTable(db, zName, 0)!=0 ){ 3120 3126 sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); 3121 3127 goto exit_create_index; 3122 3128 } 3123 3129 } 3124 3130 if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ ................................................................................ 3147 3153 ** The "vtab_err.test" test demonstrates the need of this statement. */ 3148 3154 if( IN_SPECIAL_PARSE ) zName[7]++; 3149 3155 } 3150 3156 3151 3157 /* Check for authorization to create an index. 3152 3158 */ 3153 3159 #ifndef SQLITE_OMIT_AUTHORIZATION 3154 - if( !IN_RENAME_COLUMN ){ 3160 + if( !IN_RENAME_OBJECT ){ 3155 3161 const char *zDb = pDb->zDbSName; 3156 3162 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ 3157 3163 goto exit_create_index; 3158 3164 } 3159 3165 i = SQLITE_CREATE_INDEX; 3160 3166 if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; 3161 3167 if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ ................................................................................ 3235 3241 ** populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[]. 3236 3242 ** 3237 3243 ** TODO: Issue a warning if two or more columns of the index are identical. 3238 3244 ** TODO: Issue a warning if the table primary key is used as part of the 3239 3245 ** index key. 3240 3246 */ 3241 3247 pListItem = pList->a; 3242 - if( IN_RENAME_COLUMN ){ 3248 + if( IN_RENAME_OBJECT ){ 3243 3249 pIndex->aColExpr = pList; 3244 3250 pList = 0; 3245 3251 } 3246 3252 for(i=0; i<pIndex->nKeyCol; i++, pListItem++){ 3247 3253 Expr *pCExpr; /* The i-th index expression */ 3248 3254 int requestedSortOrder; /* ASC or DESC on the i-th expression */ 3249 3255 const char *zColl; /* Collation sequence name */ ................................................................................ 3395 3401 } 3396 3402 if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType; 3397 3403 goto exit_create_index; 3398 3404 } 3399 3405 } 3400 3406 } 3401 3407 3402 - if( !IN_RENAME_COLUMN ){ 3408 + if( !IN_RENAME_OBJECT ){ 3403 3409 3404 3410 /* Link the new Index structure to its table and to the other 3405 3411 ** in-memory database structures. 3406 3412 */ 3407 3413 assert( pParse->nErr==0 ); 3408 3414 if( db->init.busy ){ 3409 3415 Index *p; ................................................................................ 3513 3519 pOther = pOther->pNext; 3514 3520 } 3515 3521 pIndex->pNext = pOther->pNext; 3516 3522 pOther->pNext = pIndex; 3517 3523 } 3518 3524 pIndex = 0; 3519 3525 } 3520 - else if( IN_RENAME_COLUMN ){ 3526 + else if( IN_RENAME_OBJECT ){ 3521 3527 assert( pParse->pNewIndex==0 ); 3522 3528 pParse->pNewIndex = pIndex; 3523 3529 pIndex = 0; 3524 3530 } 3525 3531 3526 3532 /* Clean up before exiting */ 3527 3533 exit_create_index: ................................................................................ 3709 3715 &i 3710 3716 ); 3711 3717 if( i<0 ){ 3712 3718 sqlite3IdListDelete(db, pList); 3713 3719 return 0; 3714 3720 } 3715 3721 pList->a[i].zName = sqlite3NameFromToken(db, pToken); 3716 - if( IN_RENAME_COLUMN && pList->a[i].zName ){ 3722 + if( IN_RENAME_OBJECT && pList->a[i].zName ){ 3717 3723 sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); 3718 3724 } 3719 3725 return pList; 3720 3726 } 3721 3727 3722 3728 /* 3723 3729 ** Delete an IdList. ................................................................................ 3958 3964 } 3959 3965 p = sqlite3SrcListAppend(db, p, pTable, pDatabase); 3960 3966 if( p==0 ){ 3961 3967 goto append_from_error; 3962 3968 } 3963 3969 assert( p->nSrc>0 ); 3964 3970 pItem = &p->a[p->nSrc-1]; 3971 + if( IN_RENAME_OBJECT && pItem->zName ){ 3972 + Token *pToken = (pDatabase && pDatabase->z) ? pDatabase : pTable; 3973 + sqlite3RenameTokenMap(pParse, pItem->zName, pToken); 3974 + } 3965 3975 assert( pAlias!=0 ); 3966 3976 if( pAlias->n ){ 3967 3977 pItem->zAlias = sqlite3NameFromToken(db, pAlias); 3968 3978 } 3969 3979 pItem->pSelect = pSubquery; 3970 3980 pItem->pOn = pOn; 3971 3981 pItem->pUsing = pUsing;
Changes to src/expr.c.
1662 1662 if( pList ){ 1663 1663 struct ExprList_item *pItem; 1664 1664 assert( pList->nExpr>0 ); 1665 1665 pItem = &pList->a[pList->nExpr-1]; 1666 1666 assert( pItem->zName==0 ); 1667 1667 pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); 1668 1668 if( dequote ) sqlite3Dequote(pItem->zName); 1669 - if( IN_RENAME_COLUMN ){ 1669 + if( IN_RENAME_OBJECT ){ 1670 1670 sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName); 1671 1671 } 1672 1672 } 1673 1673 } 1674 1674 1675 1675 /* 1676 1676 ** Set the ExprList.a[].zSpan element of the most recently added item ................................................................................ 3737 3737 ** see if it is a column in a virtual table. This is done because 3738 3738 ** the left operand of infix functions (the operand we want to 3739 3739 ** control overloading) ends up as the second argument to the 3740 3740 ** function. The expression "A glob B" is equivalent to 3741 3741 ** "glob(B,A). We want to use the A in "A glob B" to test 3742 3742 ** for function overloading. But we use the B term in "glob(B,A)". 3743 3743 */ 3744 - if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ 3744 + if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ 3745 3745 pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); 3746 3746 }else if( nFarg>0 ){ 3747 3747 pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); 3748 3748 } 3749 3749 #endif 3750 3750 if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ 3751 3751 if( !pColl ) pColl = db->pDfltColl;
Changes to src/main.c.
1325 1325 const char *sqlite3ErrName(int rc){ 1326 1326 const char *zName = 0; 1327 1327 int i, origRc = rc; 1328 1328 for(i=0; i<2 && zName==0; i++, rc &= 0xff){ 1329 1329 switch( rc ){ 1330 1330 case SQLITE_OK: zName = "SQLITE_OK"; break; 1331 1331 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; 1332 + case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break; 1332 1333 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; 1333 1334 case SQLITE_PERM: zName = "SQLITE_PERM"; break; 1334 1335 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; 1335 1336 case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; 1336 1337 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; 1337 1338 case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break; 1338 1339 case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break;
Changes to src/pager.c.
993 993 /* 994 994 ** Return a pointer to a human readable string in a static buffer 995 995 ** containing the state of the Pager object passed as an argument. This 996 996 ** is intended to be used within debuggers. For example, as an alternative 997 997 ** to "print *pPager" in gdb: 998 998 ** 999 999 ** (gdb) printf "%s", print_pager_state(pPager) 1000 +** 1001 +** This routine has external linkage in order to suppress compiler warnings 1002 +** about an unused function. It is enclosed within SQLITE_DEBUG and so does 1003 +** not appear in normal builds. 1000 1004 */ 1001 -static char *print_pager_state(Pager *p){ 1005 +char *print_pager_state(Pager *p){ 1002 1006 static char zRet[1024]; 1003 1007 1004 1008 sqlite3_snprintf(1024, zRet, 1005 1009 "Filename: %s\n" 1006 1010 "State: %s errCode=%d\n" 1007 1011 "Lock: %s\n" 1008 1012 "Locking mode: locking_mode=%s\n" ................................................................................ 7273 7277 ** 7274 7278 ** * Temporary databases cannot have _WAL journalmode. 7275 7279 ** 7276 7280 ** The returned indicate the current (possibly updated) journal-mode. 7277 7281 */ 7278 7282 int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ 7279 7283 u8 eOld = pPager->journalMode; /* Prior journalmode */ 7280 - 7281 -#ifdef SQLITE_DEBUG 7282 - /* The print_pager_state() routine is intended to be used by the debugger 7283 - ** only. We invoke it once here to suppress a compiler warning. */ 7284 - print_pager_state(pPager); 7285 -#endif 7286 - 7287 7284 7288 7285 /* The eMode parameter is always valid */ 7289 7286 assert( eMode==PAGER_JOURNALMODE_DELETE 7290 7287 || eMode==PAGER_JOURNALMODE_TRUNCATE 7291 7288 || eMode==PAGER_JOURNALMODE_PERSIST 7292 7289 || eMode==PAGER_JOURNALMODE_OFF 7293 7290 || eMode==PAGER_JOURNALMODE_WAL
Changes to src/parse.y.
321 321 } 322 322 ccons ::= DEFAULT scanpt id(X). { 323 323 Expr *p = tokenExpr(pParse, TK_STRING, X); 324 324 if( p ){ 325 325 sqlite3ExprIdToTrueFalse(p); 326 326 testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); 327 327 } 328 - sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n); 328 + sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n); 329 329 } 330 330 331 331 // In addition to the type name, we also care about the primary key and 332 332 // UNIQUE constraints. 333 333 // 334 334 ccons ::= NULL onconf. 335 335 ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} ................................................................................ 679 679 680 680 %type dbnm {Token} 681 681 dbnm(A) ::= . {A.z=0; A.n=0;} 682 682 dbnm(A) ::= DOT nm(X). {A = X;} 683 683 684 684 %type fullname {SrcList*} 685 685 %destructor fullname {sqlite3SrcListDelete(pParse->db, $$);} 686 -fullname(A) ::= nm(X). 687 - {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/} 688 -fullname(A) ::= nm(X) DOT nm(Y). 689 - {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/} 686 +fullname(A) ::= nm(X). { 687 + A = sqlite3SrcListAppend(pParse->db,0,&X,0); 688 + if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &X); 689 +} 690 +fullname(A) ::= nm(X) DOT nm(Y). { 691 + A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); 692 + if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &Y); 693 +} 690 694 691 695 %type xfullname {SrcList*} 692 696 %destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);} 693 697 xfullname(A) ::= nm(X). 694 698 {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/} 695 699 xfullname(A) ::= nm(X) DOT nm(Y). 696 700 {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/} ................................................................................ 950 954 if( sqlite3Isquote(p->u.zToken[0]) ){ 951 955 if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted; 952 956 sqlite3Dequote(p->u.zToken); 953 957 } 954 958 #if SQLITE_MAX_EXPR_DEPTH>0 955 959 p->nHeight = 1; 956 960 #endif 957 - if( IN_RENAME_COLUMN ){ 961 + if( IN_RENAME_OBJECT ){ 958 962 return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t); 959 963 } 960 964 } 961 965 return p; 962 966 } 963 967 964 968 } ................................................................................ 966 970 expr(A) ::= term(A). 967 971 expr(A) ::= LP expr(X) RP. {A = X;} 968 972 expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} 969 973 expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} 970 974 expr(A) ::= nm(X) DOT nm(Y). { 971 975 Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); 972 976 Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); 973 - if( IN_RENAME_COLUMN ) sqlite3RenameTokenMap(pParse, (void*)temp2, &Y); 977 + if( IN_RENAME_OBJECT ){ 978 + sqlite3RenameTokenMap(pParse, (void*)temp2, &Y); 979 + sqlite3RenameTokenMap(pParse, (void*)temp1, &X); 980 + } 974 981 A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); 975 982 } 976 983 expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { 977 984 Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); 978 985 Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); 979 986 Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1); 980 987 Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); 981 - if( IN_RENAME_COLUMN ) sqlite3RenameTokenMap(pParse, (void*)temp3, &Z); 988 + if( IN_RENAME_OBJECT ){ 989 + sqlite3RenameTokenMap(pParse, (void*)temp3, &Z); 990 + sqlite3RenameTokenMap(pParse, (void*)temp2, &Y); 991 + } 982 992 A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); 983 993 } 984 994 term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} 985 995 term(A) ::= STRING(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} 986 996 term(A) ::= INTEGER(X). { 987 997 A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1); 988 998 } ................................................................................ 1273 1283 ///////////////////////////// The CREATE INDEX command /////////////////////// 1274 1284 // 1275 1285 cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) 1276 1286 ON nm(Y) LP sortlist(Z) RP where_opt(W). { 1277 1287 sqlite3CreateIndex(pParse, &X, &D, 1278 1288 sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U, 1279 1289 &S, W, SQLITE_SO_ASC, NE, SQLITE_IDXTYPE_APPDEF); 1290 + if( IN_RENAME_OBJECT && pParse->pNewIndex ){ 1291 + sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &Y); 1292 + } 1280 1293 } 1281 1294 1282 1295 %type uniqueflag {int} 1283 1296 uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} 1284 1297 uniqueflag(A) ::= . {A = OE_None;} 1285 1298 1286 1299 ................................................................................ 1321 1334 if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED) 1322 1335 && pParse->db->init.busy==0 1323 1336 ){ 1324 1337 sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"", 1325 1338 pIdToken->n, pIdToken->z); 1326 1339 } 1327 1340 sqlite3ExprListSetName(pParse, p, pIdToken, 1); 1328 - if( IN_RENAME_COLUMN && p ){ 1329 - sqlite3RenameTokenMap(pParse, (void*)(p->a[p->nExpr-1].zName), pIdToken); 1330 - } 1331 1341 return p; 1332 1342 } 1333 1343 } // end %include 1334 1344 1335 1345 eidlist_opt(A) ::= . {A = 0;} 1336 1346 eidlist_opt(A) ::= LP eidlist(X) RP. {A = X;} 1337 1347 eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z). {
Changes to src/pragma.c.
2218 2218 sqlite3_str_appendall(&acc, "CREATE TABLE x"); 2219 2219 for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){ 2220 2220 sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]); 2221 2221 cSep = ','; 2222 2222 } 2223 2223 if( i==0 ){ 2224 2224 sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName); 2225 - cSep = ','; 2226 2225 i++; 2227 2226 } 2228 2227 j = 0; 2229 2228 if( pPragma->mPragFlg & PragFlg_Result1 ){ 2230 2229 sqlite3_str_appendall(&acc, ",arg HIDDEN"); 2231 2230 j++; 2232 2231 }
Changes to src/prepare.c.
89 89 db->init.iDb = iDb; 90 90 db->init.newTnum = sqlite3Atoi(argv[1]); 91 91 db->init.orphanTrigger = 0; 92 92 TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); 93 93 rc = db->errCode; 94 94 assert( (rc&0xFF)==(rcp&0xFF) ); 95 95 db->init.iDb = saved_iDb; 96 - assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); 96 + /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */ 97 97 if( SQLITE_OK!=rc ){ 98 98 if( db->init.orphanTrigger ){ 99 99 assert( iDb==1 ); 100 100 }else{ 101 101 pData->rc = rc; 102 102 if( rc==SQLITE_NOMEM ){ 103 103 sqlite3OomFault(db);
Changes to src/resolve.c.
260 260 } 261 261 if( zTab ){ 262 262 const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; 263 263 assert( zTabName!=0 ); 264 264 if( sqlite3StrICmp(zTabName, zTab)!=0 ){ 265 265 continue; 266 266 } 267 + if( IN_RENAME_OBJECT && pItem->zAlias ){ 268 + sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab); 269 + } 267 270 } 268 271 if( 0==(cntTab++) ){ 269 272 pMatch = pItem; 270 273 } 271 274 for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ 272 275 if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ 273 276 /* If there has been exactly one prior match and this match ................................................................................ 345 348 iCol = -1; 346 349 } 347 350 if( iCol<pTab->nCol ){ 348 351 cnt++; 349 352 #ifndef SQLITE_OMIT_UPSERT 350 353 if( pExpr->iTable==2 ){ 351 354 testcase( iCol==(-1) ); 352 - if( IN_RENAME_COLUMN ){ 355 + if( IN_RENAME_OBJECT ){ 353 356 pExpr->iColumn = iCol; 354 357 pExpr->pTab = pTab; 355 358 eNewExprOp = TK_COLUMN; 356 359 }else{ 357 360 pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; 358 361 eNewExprOp = TK_REGISTER; 359 362 ExprSetProperty(pExpr, EP_Alias); ................................................................................ 438 441 sqlite3ErrorMsg(pParse, "row value misused"); 439 442 return WRC_Abort; 440 443 } 441 444 resolveAlias(pParse, pEList, j, pExpr, "", nSubquery); 442 445 cnt = 1; 443 446 pMatch = 0; 444 447 assert( zTab==0 && zDb==0 ); 445 - if( IN_RENAME_COLUMN ){ 448 + if( IN_RENAME_OBJECT ){ 446 449 sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr); 447 450 } 448 451 goto lookupname_end; 449 452 } 450 453 } 451 454 } 452 455 ................................................................................ 668 671 Expr *pRight; 669 672 670 673 if( pExpr->op==TK_ID ){ 671 674 zDb = 0; 672 675 zTable = 0; 673 676 zColumn = pExpr->u.zToken; 674 677 }else{ 678 + Expr *pLeft = pExpr->pLeft; 675 679 notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr); 676 680 pRight = pExpr->pRight; 677 681 if( pRight->op==TK_ID ){ 678 682 zDb = 0; 679 - zTable = pExpr->pLeft->u.zToken; 680 683 }else{ 681 684 assert( pRight->op==TK_DOT ); 682 - zDb = pExpr->pLeft->u.zToken; 683 - zTable = pRight->pLeft->u.zToken; 685 + zDb = pLeft->u.zToken; 686 + pLeft = pRight->pLeft; 684 687 pRight = pRight->pRight; 685 688 } 689 + zTable = pLeft->u.zToken; 686 690 zColumn = pRight->u.zToken; 687 - if( IN_RENAME_COLUMN ){ 691 + if( IN_RENAME_OBJECT ){ 688 692 sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); 689 693 } 694 + if( IN_RENAME_OBJECT ){ 695 + sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); 696 + } 690 697 } 691 698 return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); 692 699 } 693 700 694 701 /* Resolve function names 695 702 */ 696 703 case TK_FUNCTION: { ................................................................................ 765 772 ** sqlite_version() that might change over time cannot be used 766 773 ** in an index. */ 767 774 notValid(pParse, pNC, "non-deterministic functions", 768 775 NC_IdxExpr|NC_PartIdx); 769 776 } 770 777 } 771 778 772 - if( 0==IN_RENAME_COLUMN ){ 779 + if( 0==IN_RENAME_OBJECT ){ 773 780 #ifndef SQLITE_OMIT_WINDOWFUNC 774 781 assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX) 775 782 || (pDef->xValue==0 && pDef->xInverse==0) 776 783 || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) 777 784 ); 778 785 if( pDef && pDef->xValue==0 && pExpr->pWin ){ 779 786 sqlite3ErrorMsg(pParse,
Changes to src/rowset.c.
120 120 /* 121 121 ** Allowed values for RowSet.rsFlags 122 122 */ 123 123 #define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ 124 124 #define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ 125 125 126 126 /* 127 -** Turn bulk memory into a RowSet object. N bytes of memory 128 -** are available at pSpace. The db pointer is used as a memory context 129 -** for any subsequent allocations that need to occur. 130 -** Return a pointer to the new RowSet object. 131 -** 132 -** It must be the case that N is sufficient to make a Rowset. If not 133 -** an assertion fault occurs. 134 -** 135 -** If N is larger than the minimum, use the surplus as an initial 136 -** allocation of entries available to be filled. 127 +** Allocate a RowSet object. Return NULL if a memory allocation 128 +** error occurs. 137 129 */ 138 -RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ 139 - RowSet *p; 140 - assert( N >= ROUND8(sizeof(*p)) ); 141 - p = pSpace; 142 - p->pChunk = 0; 143 - p->db = db; 144 - p->pEntry = 0; 145 - p->pLast = 0; 146 - p->pForest = 0; 147 - p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); 148 - p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); 149 - p->rsFlags = ROWSET_SORTED; 150 - p->iBatch = 0; 130 +RowSet *sqlite3RowSetInit(sqlite3 *db){ 131 + RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p)); 132 + if( p ){ 133 + int N = sqlite3DbMallocSize(db, p); 134 + p->pChunk = 0; 135 + p->db = db; 136 + p->pEntry = 0; 137 + p->pLast = 0; 138 + p->pForest = 0; 139 + p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); 140 + p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); 141 + p->rsFlags = ROWSET_SORTED; 142 + p->iBatch = 0; 143 + } 151 144 return p; 152 145 } 153 146 154 147 /* 155 148 ** Deallocate all chunks from a RowSet. This frees all memory that 156 149 ** the RowSet has allocated over its lifetime. This routine is 157 150 ** the destructor for the RowSet. 158 151 */ 159 -void sqlite3RowSetClear(RowSet *p){ 152 +void sqlite3RowSetClear(void *pArg){ 153 + RowSet *p = (RowSet*)pArg; 160 154 struct RowSetChunk *pChunk, *pNextChunk; 161 155 for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ 162 156 pNextChunk = pChunk->pNextChunk; 163 157 sqlite3DbFree(p->db, pChunk); 164 158 } 165 159 p->pChunk = 0; 166 160 p->nFresh = 0; 167 161 p->pEntry = 0; 168 162 p->pLast = 0; 169 163 p->pForest = 0; 170 164 p->rsFlags = ROWSET_SORTED; 171 165 } 166 + 167 +/* 168 +** Deallocate all chunks from a RowSet. This frees all memory that 169 +** the RowSet has allocated over its lifetime. This routine is 170 +** the destructor for the RowSet. 171 +*/ 172 +void sqlite3RowSetDelete(void *pArg){ 173 + sqlite3RowSetClear(pArg); 174 + sqlite3DbFree(((RowSet*)pArg)->db, pArg); 175 +} 172 176 173 177 /* 174 178 ** Allocate a new RowSetEntry object that is associated with the 175 179 ** given RowSet. Return a pointer to the new and completely uninitialized 176 180 ** objected. 177 181 ** 178 182 ** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
Changes to src/sqlite.h.in.
468 468 ** on a per database connection basis using the 469 469 ** [sqlite3_extended_result_codes()] API. Or, the extended code for 470 470 ** the most recent error can be obtained using 471 471 ** [sqlite3_extended_errcode()]. 472 472 */ 473 473 #define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8)) 474 474 #define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8)) 475 +#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8)) 475 476 #define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) 476 477 #define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) 477 478 #define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) 478 479 #define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) 479 480 #define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) 480 481 #define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) 481 482 #define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) ................................................................................ 6436 6437 #define SQLITE_INDEX_CONSTRAINT_GLOB 66 6437 6438 #define SQLITE_INDEX_CONSTRAINT_REGEXP 67 6438 6439 #define SQLITE_INDEX_CONSTRAINT_NE 68 6439 6440 #define SQLITE_INDEX_CONSTRAINT_ISNOT 69 6440 6441 #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 6441 6442 #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 6442 6443 #define SQLITE_INDEX_CONSTRAINT_IS 72 6444 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 6443 6445 6444 6446 /* 6445 6447 ** CAPI3REF: Register A Virtual Table Implementation 6446 6448 ** METHOD: sqlite3 6447 6449 ** 6448 6450 ** ^These routines are used to register a new [virtual table module] name. 6449 6451 ** ^Module names must be registered before ................................................................................ 9048 9050 ** must have no active statements (SELECT statements that have been passed 9049 9051 ** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()). 9050 9052 ** SQLITE_ERROR is returned if either of these conditions is violated, or 9051 9053 ** if schema S does not exist, or if the snapshot object is invalid. 9052 9054 ** 9053 9055 ** ^A call to sqlite3_snapshot_open() will fail to open if the specified 9054 9056 ** snapshot has been overwritten by a [checkpoint]. In this case 9055 -** SQLITE_BUSY_SNAPSHOT is returned. 9057 +** SQLITE_ERROR_SNAPSHOT is returned. 9056 9058 ** 9057 9059 ** If there is already a read transaction open when this function is 9058 9060 ** invoked, then the same read transaction remains open (on the same 9059 -** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_BUSY_SNAPSHOT 9061 +** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT 9060 9062 ** is returned. If another error code - for example SQLITE_PROTOCOL or an 9061 9063 ** SQLITE_IOERR error code - is returned, then the final state of the 9062 9064 ** read transaction is undefined. If SQLITE_OK is returned, then the 9063 9065 ** read transaction is now open on database snapshot P. 9064 9066 ** 9065 9067 ** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the 9066 9068 ** database connection D does not know that the database file for
Changes to src/sqliteInt.h.
787 787 /* 788 788 ** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer 789 789 */ 790 790 #ifndef SQLITE_PTRSIZE 791 791 # if defined(__SIZEOF_POINTER__) 792 792 # define SQLITE_PTRSIZE __SIZEOF_POINTER__ 793 793 # elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ 794 - defined(_M_ARM) || defined(__arm__) || defined(__x86) 794 + defined(_M_ARM) || defined(__arm__) || defined(__x86) || \ 795 + (defined(__TOS_AIX__) && !defined(__64BIT__)) 795 796 # define SQLITE_PTRSIZE 4 796 797 # else 797 798 # define SQLITE_PTRSIZE 8 798 799 # endif 799 800 #endif 800 801 801 802 /* The uptr type is an unsigned integer large enough to hold a pointer ................................................................................ 828 829 ** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined 829 830 ** at run-time. 830 831 */ 831 832 #ifndef SQLITE_BYTEORDER 832 833 # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ 833 834 defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ 834 835 defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ 835 - defined(__arm__) 836 + defined(__arm__) || defined(_M_ARM64) 836 837 # define SQLITE_BYTEORDER 1234 837 838 # elif defined(sparc) || defined(__ppc__) 838 839 # define SQLITE_BYTEORDER 4321 839 840 # else 840 841 # define SQLITE_BYTEORDER 0 841 842 # endif 842 843 #endif ................................................................................ 3119 3120 RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ 3120 3121 #endif 3121 3122 }; 3122 3123 3123 3124 #define PARSE_MODE_NORMAL 0 3124 3125 #define PARSE_MODE_DECLARE_VTAB 1 3125 3126 #define PARSE_MODE_RENAME_COLUMN 2 3127 +#define PARSE_MODE_RENAME_TABLE 3 3126 3128 3127 3129 /* 3128 3130 ** Sizes and pointers of various parts of the Parse object. 3129 3131 */ 3130 3132 #define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/ 3131 3133 #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ 3132 3134 #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ ................................................................................ 3138 3140 #ifdef SQLITE_OMIT_VIRTUALTABLE 3139 3141 #define IN_DECLARE_VTAB 0 3140 3142 #else 3141 3143 #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB) 3142 3144 #endif 3143 3145 3144 3146 #if defined(SQLITE_OMIT_ALTERTABLE) 3145 - #define IN_RENAME_COLUMN 0 3147 + #define IN_RENAME_OBJECT 0 3146 3148 #else 3147 - #define IN_RENAME_COLUMN (pParse->eParseMode==PARSE_MODE_RENAME_COLUMN) 3149 + #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN) 3148 3150 #endif 3149 3151 3150 3152 #if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE) 3151 3153 #define IN_SPECIAL_PARSE 0 3152 3154 #else 3153 3155 #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL) 3154 3156 #endif ................................................................................ 3851 3853 void sqlite3BitvecClear(Bitvec*, u32, void*); 3852 3854 void sqlite3BitvecDestroy(Bitvec*); 3853 3855 u32 sqlite3BitvecSize(Bitvec*); 3854 3856 #ifndef SQLITE_UNTESTABLE 3855 3857 int sqlite3BitvecBuiltinTest(int,int*); 3856 3858 #endif 3857 3859 3858 -RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); 3859 -void sqlite3RowSetClear(RowSet*); 3860 +RowSet *sqlite3RowSetInit(sqlite3*); 3861 +void sqlite3RowSetDelete(void*); 3862 +void sqlite3RowSetClear(void*); 3860 3863 void sqlite3RowSetInsert(RowSet*, i64); 3861 3864 int sqlite3RowSetTest(RowSet*, int iBatch, i64); 3862 3865 int sqlite3RowSetNext(RowSet*, i64*); 3863 3866 3864 3867 void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int); 3865 3868 3866 3869 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
Changes to src/tokenize.c.
691 691 if( !IN_SPECIAL_PARSE ){ 692 692 /* If the pParse->declareVtab flag is set, do not delete any table 693 693 ** structure built up in pParse->pNewTable. The calling code (see vtab.c) 694 694 ** will take responsibility for freeing the Table structure. 695 695 */ 696 696 sqlite3DeleteTable(db, pParse->pNewTable); 697 697 } 698 - if( !IN_RENAME_COLUMN ){ 698 + if( !IN_RENAME_OBJECT ){ 699 699 sqlite3DeleteTrigger(db, pParse->pNewTrigger); 700 700 } 701 701 702 702 if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree); 703 703 sqlite3DbFree(db, pParse->pVList); 704 704 while( pParse->pAinc ){ 705 705 AutoincInfo *p = pParse->pAinc;
Changes to src/trigger.c.
177 177 /* Check that the trigger name is not reserved and that no trigger of the 178 178 ** specified name exists */ 179 179 zName = sqlite3NameFromToken(db, pName); 180 180 if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ 181 181 goto trigger_cleanup; 182 182 } 183 183 assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); 184 - if( !IN_RENAME_COLUMN ){ 184 + if( !IN_RENAME_OBJECT ){ 185 185 if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ 186 186 if( !noErr ){ 187 187 sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); 188 188 }else{ 189 189 assert( !db->init.busy ); 190 190 sqlite3CodeVerifySchema(pParse, iDb); 191 191 } ................................................................................ 210 210 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ 211 211 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" 212 212 " trigger on table: %S", pTableName, 0); 213 213 goto trigger_cleanup; 214 214 } 215 215 216 216 #ifndef SQLITE_OMIT_AUTHORIZATION 217 - if( !IN_RENAME_COLUMN ){ 217 + if( !IN_RENAME_OBJECT ){ 218 218 int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); 219 219 int code = SQLITE_CREATE_TRIGGER; 220 220 const char *zDb = db->aDb[iTabDb].zDbSName; 221 221 const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; 222 222 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; 223 223 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ 224 224 goto trigger_cleanup; ................................................................................ 244 244 pTrigger->zName = zName; 245 245 zName = 0; 246 246 pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); 247 247 pTrigger->pSchema = db->aDb[iDb].pSchema; 248 248 pTrigger->pTabSchema = pTab->pSchema; 249 249 pTrigger->op = (u8)op; 250 250 pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; 251 - if( IN_RENAME_COLUMN ){ 251 + if( IN_RENAME_OBJECT ){ 252 + sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName); 252 253 pTrigger->pWhen = pWhen; 253 254 pWhen = 0; 254 255 }else{ 255 256 pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE); 256 257 } 257 258 pTrigger->pColumns = pColumns; 258 259 pColumns = 0; ................................................................................ 301 302 if( sqlite3FixTriggerStep(&sFix, pTrig->step_list) 302 303 || sqlite3FixExpr(&sFix, pTrig->pWhen) 303 304 ){ 304 305 goto triggerfinish_cleanup; 305 306 } 306 307 307 308 #ifndef SQLITE_OMIT_ALTERTABLE 308 - if( IN_RENAME_COLUMN ){ 309 + if( IN_RENAME_OBJECT ){ 309 310 assert( !db->init.busy ); 310 311 pParse->pNewTrigger = pTrig; 311 312 pTrig = 0; 312 313 }else 313 314 #endif 314 315 315 316 /* if we are not initializing, ................................................................................ 349 350 pLink->pNext = pTab->pTrigger; 350 351 pTab->pTrigger = pLink; 351 352 } 352 353 } 353 354 354 355 triggerfinish_cleanup: 355 356 sqlite3DeleteTrigger(db, pTrig); 356 - assert( IN_RENAME_COLUMN || !pParse->pNewTrigger ); 357 + assert( IN_RENAME_OBJECT || !pParse->pNewTrigger ); 357 358 sqlite3DeleteTriggerStep(db, pStepList); 358 359 } 359 360 360 361 /* 361 362 ** Duplicate a range of text from an SQL statement, then convert all 362 363 ** whitespace characters into ordinary space characters. 363 364 */ ................................................................................ 396 397 /* 397 398 ** Allocate space to hold a new trigger step. The allocated space 398 399 ** holds both the TriggerStep object and the TriggerStep.target.z string. 399 400 ** 400 401 ** If an OOM error occurs, NULL is returned and db->mallocFailed is set. 401 402 */ 402 403 static TriggerStep *triggerStepAllocate( 403 - sqlite3 *db, /* Database connection */ 404 + Parse *pParse, /* Parser context */ 404 405 u8 op, /* Trigger opcode */ 405 406 Token *pName, /* The target name */ 406 407 const char *zStart, /* Start of SQL text */ 407 408 const char *zEnd /* End of SQL text */ 408 409 ){ 410 + sqlite3 *db = pParse->db; 409 411 TriggerStep *pTriggerStep; 410 412 411 413 pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); 412 414 if( pTriggerStep ){ 413 415 char *z = (char*)&pTriggerStep[1]; 414 416 memcpy(z, pName->z, pName->n); 415 417 sqlite3Dequote(z); 416 418 pTriggerStep->zTarget = z; 417 419 pTriggerStep->op = op; 418 420 pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); 421 + if( IN_RENAME_OBJECT ){ 422 + sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName); 423 + } 419 424 } 420 425 return pTriggerStep; 421 426 } 422 427 423 428 /* 424 429 ** Build a trigger step out of an INSERT statement. Return a pointer 425 430 ** to the new trigger step. ................................................................................ 438 443 const char *zEnd /* End of SQL text */ 439 444 ){ 440 445 sqlite3 *db = pParse->db; 441 446 TriggerStep *pTriggerStep; 442 447 443 448 assert(pSelect != 0 || db->mallocFailed); 444 449 445 - pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); 450 + pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd); 446 451 if( pTriggerStep ){ 447 - if( IN_RENAME_COLUMN ){ 452 + if( IN_RENAME_OBJECT ){ 448 453 pTriggerStep->pSelect = pSelect; 449 454 pSelect = 0; 450 455 }else{ 451 456 pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); 452 457 } 453 458 pTriggerStep->pIdList = pColumn; 454 459 pTriggerStep->pUpsert = pUpsert; ................................................................................ 477 482 u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ 478 483 const char *zStart, /* Start of SQL text */ 479 484 const char *zEnd /* End of SQL text */ 480 485 ){ 481 486 sqlite3 *db = pParse->db; 482 487 TriggerStep *pTriggerStep; 483 488 484 - pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd); 489 + pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd); 485 490 if( pTriggerStep ){ 486 - if( IN_RENAME_COLUMN ){ 491 + if( IN_RENAME_OBJECT ){ 487 492 pTriggerStep->pExprList = pEList; 488 493 pTriggerStep->pWhere = pWhere; 489 494 pEList = 0; 490 495 pWhere = 0; 491 496 }else{ 492 497 pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); 493 498 pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); ................................................................................ 510 515 Expr *pWhere, /* The WHERE clause */ 511 516 const char *zStart, /* Start of SQL text */ 512 517 const char *zEnd /* End of SQL text */ 513 518 ){ 514 519 sqlite3 *db = pParse->db; 515 520 TriggerStep *pTriggerStep; 516 521 517 - pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd); 522 + pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd); 518 523 if( pTriggerStep ){ 519 - if( IN_RENAME_COLUMN ){ 524 + if( IN_RENAME_OBJECT ){ 520 525 pTriggerStep->pWhere = pWhere; 521 526 pWhere = 0; 522 527 }else{ 523 528 pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); 524 529 } 525 530 pTriggerStep->orconf = OE_Default; 526 531 }
Changes to src/upsert.c.
200 200 Table *pTab, /* The table being updated */ 201 201 Index *pIdx, /* The UNIQUE constraint that failed */ 202 202 int iCur /* Cursor for pIdx (or pTab if pIdx==NULL) */ 203 203 ){ 204 204 Vdbe *v = pParse->pVdbe; 205 205 sqlite3 *db = pParse->db; 206 206 SrcList *pSrc; /* FROM clause for the UPDATE */ 207 - int iDataCur = pUpsert->iDataCur; 207 + int iDataCur; 208 208 209 209 assert( v!=0 ); 210 + assert( pUpsert!=0 ); 210 211 VdbeNoopComment((v, "Begin DO UPDATE of UPSERT")); 212 + iDataCur = pUpsert->iDataCur; 211 213 if( pIdx && iCur!=iDataCur ){ 212 214 if( HasRowid(pTab) ){ 213 215 int regRowid = sqlite3GetTempReg(pParse); 214 216 sqlite3VdbeAddOp2(v, OP_IdxRowid, iCur, regRowid); 215 217 sqlite3VdbeAddOp3(v, OP_SeekRowid, iDataCur, 0, regRowid); 216 218 VdbeCoverage(v); 217 219 sqlite3ReleaseTempReg(pParse, regRowid);
Changes to src/vdbe.c.
498 498 printf(" si:%lld", p->u.i); 499 499 }else if( p->flags & MEM_Int ){ 500 500 printf(" i:%lld", p->u.i); 501 501 #ifndef SQLITE_OMIT_FLOATING_POINT 502 502 }else if( p->flags & MEM_Real ){ 503 503 printf(" r:%g", p->u.r); 504 504 #endif 505 - }else if( p->flags & MEM_RowSet ){ 505 + }else if( sqlite3VdbeMemIsRowSet(p) ){ 506 506 printf(" (rowset)"); 507 507 }else{ 508 508 char zBuf[200]; 509 509 sqlite3VdbeMemPrettyPrint(p, zBuf); 510 510 printf(" %s", zBuf); 511 511 } 512 512 if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype); ................................................................................ 5910 5910 ** 5911 5911 ** An assertion fails if P2 is not an integer. 5912 5912 */ 5913 5913 case OP_RowSetAdd: { /* in1, in2 */ 5914 5914 pIn1 = &aMem[pOp->p1]; 5915 5915 pIn2 = &aMem[pOp->p2]; 5916 5916 assert( (pIn2->flags & MEM_Int)!=0 ); 5917 - if( (pIn1->flags & MEM_RowSet)==0 ){ 5918 - sqlite3VdbeMemSetRowSet(pIn1); 5919 - if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; 5917 + if( (pIn1->flags & MEM_Blob)==0 ){ 5918 + if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; 5920 5919 } 5921 - sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i); 5920 + assert( sqlite3VdbeMemIsRowSet(pIn1) ); 5921 + sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i); 5922 5922 break; 5923 5923 } 5924 5924 5925 5925 /* Opcode: RowSetRead P1 P2 P3 * * 5926 5926 ** Synopsis: r[P3]=rowset(P1) 5927 5927 ** 5928 5928 ** Extract the smallest value from the RowSet object in P1 ................................................................................ 5930 5930 ** Or, if RowSet object P1 is initially empty, leave P3 5931 5931 ** unchanged and jump to instruction P2. 5932 5932 */ 5933 5933 case OP_RowSetRead: { /* jump, in1, out3 */ 5934 5934 i64 val; 5935 5935 5936 5936 pIn1 = &aMem[pOp->p1]; 5937 - if( (pIn1->flags & MEM_RowSet)==0 5938 - || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 5937 + assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) ); 5938 + if( (pIn1->flags & MEM_Blob)==0 5939 + || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0 5939 5940 ){ 5940 5941 /* The boolean index is empty */ 5941 5942 sqlite3VdbeMemSetNull(pIn1); 5942 5943 VdbeBranchTaken(1,2); 5943 5944 goto jump_to_p2_and_check_for_interrupt; 5944 5945 }else{ 5945 5946 /* A value was pulled from the index */ ................................................................................ 5980 5981 pIn3 = &aMem[pOp->p3]; 5981 5982 iSet = pOp->p4.i; 5982 5983 assert( pIn3->flags&MEM_Int ); 5983 5984 5984 5985 /* If there is anything other than a rowset object in memory cell P1, 5985 5986 ** delete it now and initialize P1 with an empty rowset 5986 5987 */ 5987 - if( (pIn1->flags & MEM_RowSet)==0 ){ 5988 - sqlite3VdbeMemSetRowSet(pIn1); 5989 - if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem; 5988 + if( (pIn1->flags & MEM_Blob)==0 ){ 5989 + if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem; 5990 5990 } 5991 - 5991 + assert( sqlite3VdbeMemIsRowSet(pIn1) ); 5992 5992 assert( pOp->p4type==P4_INT32 ); 5993 5993 assert( iSet==-1 || iSet>=0 ); 5994 5994 if( iSet ){ 5995 - exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); 5995 + exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i); 5996 5996 VdbeBranchTaken(exists!=0,2); 5997 5997 if( exists ) goto jump_to_p2; 5998 5998 } 5999 5999 if( iSet>=0 ){ 6000 - sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); 6000 + sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i); 6001 6001 } 6002 6002 break; 6003 6003 } 6004 6004 6005 6005 6006 6006 #ifndef SQLITE_OMIT_TRIGGER 6007 6007 ................................................................................ 6057 6057 goto abort_due_to_error; 6058 6058 } 6059 6059 6060 6060 /* Register pRt is used to store the memory required to save the state 6061 6061 ** of the current program, and the memory required at runtime to execute 6062 6062 ** the trigger program. If this trigger has been fired before, then pRt 6063 6063 ** is already allocated. Otherwise, it must be initialized. */ 6064 - if( (pRt->flags&MEM_Frame)==0 ){ 6064 + if( (pRt->flags&MEM_Blob)==0 ){ 6065 6065 /* SubProgram.nMem is set to the number of memory cells used by the 6066 6066 ** program stored in SubProgram.aOp. As well as these, one memory 6067 6067 ** cell is required for each cursor used by the program. Set local 6068 6068 ** variable nMem (and later, VdbeFrame.nChildMem) to this value. 6069 6069 */ 6070 6070 nMem = pProgram->nMem + pProgram->nCsr; 6071 6071 assert( nMem>0 ); ................................................................................ 6075 6075 + pProgram->nCsr * sizeof(VdbeCursor*) 6076 6076 + (pProgram->nOp + 7)/8; 6077 6077 pFrame = sqlite3DbMallocZero(db, nByte); 6078 6078 if( !pFrame ){ 6079 6079 goto no_mem; 6080 6080 } 6081 6081 sqlite3VdbeMemRelease(pRt); 6082 - pRt->flags = MEM_Frame; 6083 - pRt->u.pFrame = pFrame; 6082 + pRt->flags = MEM_Blob|MEM_Dyn; 6083 + pRt->z = (char*)pFrame; 6084 + pRt->n = nByte; 6085 + pRt->xDel = sqlite3VdbeFrameMemDel; 6084 6086 6085 6087 pFrame->v = p; 6086 6088 pFrame->nChildMem = nMem; 6087 6089 pFrame->nChildCsr = pProgram->nCsr; 6088 6090 pFrame->pc = (int)(pOp - aOp); 6089 6091 pFrame->aMem = p->aMem; 6090 6092 pFrame->nMem = p->nMem; ................................................................................ 6092 6094 pFrame->nCursor = p->nCursor; 6093 6095 pFrame->aOp = p->aOp; 6094 6096 pFrame->nOp = p->nOp; 6095 6097 pFrame->token = pProgram->token; 6096 6098 #ifdef SQLITE_ENABLE_STMT_SCANSTATUS 6097 6099 pFrame->anExec = p->anExec; 6098 6100 #endif 6101 +#ifdef SQLITE_DEBUG 6102 + pFrame->iFrameMagic = SQLITE_FRAME_MAGIC; 6103 +#endif 6099 6104 6100 6105 pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem]; 6101 6106 for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){ 6102 6107 pMem->flags = MEM_Undefined; 6103 6108 pMem->db = db; 6104 6109 } 6105 6110 }else{ 6106 - pFrame = pRt->u.pFrame; 6111 + pFrame = (VdbeFrame*)pRt->z; 6112 + assert( pRt->xDel==sqlite3VdbeFrameMemDel ); 6107 6113 assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem 6108 6114 || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) ); 6109 6115 assert( pProgram->nCsr==pFrame->nChildCsr ); 6110 6116 assert( (int)(pOp - aOp)==pFrame->pc ); 6111 6117 } 6112 6118 6113 6119 p->nFrame++;
Changes to src/vdbeInt.h.
165 165 i64 *anExec; /* Event counters from parent frame */ 166 166 Mem *aMem; /* Array of memory cells for parent frame */ 167 167 VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */ 168 168 u8 *aOnce; /* Bitmask used by OP_Once */ 169 169 void *token; /* Copy of SubProgram.token */ 170 170 i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ 171 171 AuxData *pAuxData; /* Linked list of auxdata allocations */ 172 +#if SQLITE_DEBUG 173 + u32 iFrameMagic; /* magic number for sanity checking */ 174 +#endif 172 175 int nCursor; /* Number of entries in apCsr */ 173 176 int pc; /* Program Counter in parent (calling) frame */ 174 177 int nOp; /* Size of aOp array */ 175 178 int nMem; /* Number of entries in aMem */ 176 179 int nChildMem; /* Number of memory cells for child frame */ 177 180 int nChildCsr; /* Number of cursors for child frame */ 178 181 int nChange; /* Statement changes (Vdbe.nChange) */ 179 182 int nDbChange; /* Value of db->nChange */ 180 183 }; 181 184 185 +/* Magic number for sanity checking on VdbeFrame objects */ 186 +#define SQLITE_FRAME_MAGIC 0x879fb71e 187 + 188 +/* 189 +** Return a pointer to the array of registers allocated for use 190 +** by a VdbeFrame. 191 +*/ 182 192 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) 183 193 184 194 /* 185 195 ** Internally, the vdbe manipulates nearly all SQL values as Mem 186 196 ** structures. Each Mem struct may cache multiple representations (string, 187 197 ** integer etc.) of the same value. 188 198 */ ................................................................................ 189 199 struct sqlite3_value { 190 200 union MemValue { 191 201 double r; /* Real value used when MEM_Real is set in flags */ 192 202 i64 i; /* Integer value used when MEM_Int is set in flags */ 193 203 int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */ 194 204 const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ 195 205 FuncDef *pDef; /* Used only when flags==MEM_Agg */ 196 - RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ 197 - VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ 198 206 } u; 199 207 u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ 200 208 u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ 201 209 u8 eSubtype; /* Subtype for this value */ 202 210 int n; /* Number of characters in string value, excluding '\0' */ 203 211 char *z; /* String or BLOB value */ 204 212 /* ShallowCopy only needs to copy the information above */ ................................................................................ 234 242 */ 235 243 #define MEM_Null 0x0001 /* Value is NULL (or a pointer) */ 236 244 #define MEM_Str 0x0002 /* Value is a string */ 237 245 #define MEM_Int 0x0004 /* Value is an integer */ 238 246 #define MEM_Real 0x0008 /* Value is a real number */ 239 247 #define MEM_Blob 0x0010 /* Value is a BLOB */ 240 248 #define MEM_AffMask 0x001f /* Mask of affinity bits */ 241 -#define MEM_RowSet 0x0020 /* Value is a RowSet object */ 242 -#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */ 249 +/* Available 0x0020 */ 250 +/* Available 0x0040 */ 243 251 #define MEM_Undefined 0x0080 /* Value is undefined */ 244 252 #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ 245 253 #define MEM_TypeMask 0xc1ff /* Mask of type bits */ 246 254 247 255 248 256 /* Whenever Mem contains a valid string or blob representation, one of 249 257 ** the following flags must be set to determine the memory management ................................................................................ 262 270 #define MEM_Zero 0x0000 263 271 #endif 264 272 265 273 /* Return TRUE if Mem X contains dynamically allocated content - anything 266 274 ** that needs to be deallocated to avoid a leak. 267 275 */ 268 276 #define VdbeMemDynamic(X) \ 269 - (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0) 277 + (((X)->flags&(MEM_Agg|MEM_Dyn))!=0) 270 278 271 279 /* 272 280 ** Clear any existing type flags from a Mem and replace them with f 273 281 */ 274 282 #define MemSetTypeFlag(p, f) \ 275 283 ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) 276 284 ................................................................................ 475 483 #else 476 484 void sqlite3VdbeMemSetDouble(Mem*, double); 477 485 #endif 478 486 void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); 479 487 void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); 480 488 void sqlite3VdbeMemSetNull(Mem*); 481 489 void sqlite3VdbeMemSetZeroBlob(Mem*,int); 482 -void sqlite3VdbeMemSetRowSet(Mem*); 490 +#ifdef SQLITE_DEBUG 491 +int sqlite3VdbeMemIsRowSet(const Mem*); 492 +#endif 493 +int sqlite3VdbeMemSetRowSet(Mem*); 483 494 int sqlite3VdbeMemMakeWriteable(Mem*); 484 495 int sqlite3VdbeMemStringify(Mem*, u8, u8); 485 496 i64 sqlite3VdbeIntValue(Mem*); 486 497 int sqlite3VdbeMemIntegerify(Mem*); 487 498 double sqlite3VdbeRealValue(Mem*); 488 499 int sqlite3VdbeBooleanValue(Mem*, int ifNull); 489 500 void sqlite3VdbeIntegerAffinity(Mem*); ................................................................................ 496 507 #ifndef SQLITE_OMIT_WINDOWFUNC 497 508 int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); 498 509 #endif 499 510 const char *sqlite3OpcodeName(int); 500 511 int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); 501 512 int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); 502 513 int sqlite3VdbeCloseStatement(Vdbe *, int); 503 -void sqlite3VdbeFrameDelete(VdbeFrame*); 514 +#ifdef SQLITE_DEBUG 515 +int sqlite3VdbeFrameIsValid(VdbeFrame*); 516 +#endif 517 +void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ 518 +void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ 504 519 int sqlite3VdbeFrameRestore(VdbeFrame *); 505 520 #ifdef SQLITE_ENABLE_PREUPDATE_HOOK 506 521 void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int); 507 522 #endif 508 523 int sqlite3VdbeTransferError(Vdbe *p); 509 524 510 525 int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
Changes to src/vdbeaux.c.
312 312 ** 313 313 ** If the bPush flag is true, then make this opcode the parent for 314 314 ** subsequent Explains until sqlite3VdbeExplainPop() is called. 315 315 */ 316 316 void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ 317 317 if( pParse->explain==2 ){ 318 318 char *zMsg; 319 - Vdbe *v = pParse->pVdbe; 319 + Vdbe *v; 320 320 va_list ap; 321 321 int iThis; 322 322 va_start(ap, zFmt); 323 323 zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap); 324 324 va_end(ap); 325 325 v = pParse->pVdbe; 326 326 iThis = v->nOp; ................................................................................ 1657 1657 ** sqlite3MemRelease() were called from here. With -O2, this jumps 1658 1658 ** to 6.6 percent. The test case is inserting 1000 rows into a table 1659 1659 ** with no indexes using a single prepared INSERT statement, bind() 1660 1660 ** and reset(). Inserts are grouped into a transaction. 1661 1661 */ 1662 1662 testcase( p->flags & MEM_Agg ); 1663 1663 testcase( p->flags & MEM_Dyn ); 1664 - testcase( p->flags & MEM_Frame ); 1664 + testcase( p->xDel==sqlite3VdbeFrameMemDel ); 1665 1665 testcase( p->flags & MEM_RowSet ); 1666 - if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ 1666 + if( p->flags&(MEM_Agg|MEM_Dyn) ){ 1667 1667 sqlite3VdbeMemRelease(p); 1668 1668 }else if( p->szMalloc ){ 1669 1669 sqlite3DbFreeNN(db, p->zMalloc); 1670 1670 p->szMalloc = 0; 1671 1671 } 1672 1672 1673 1673 p->flags = MEM_Undefined; 1674 1674 }while( (++p)<pEnd ); 1675 1675 } 1676 1676 } 1677 + 1678 +#ifdef SQLITE_DEBUG 1679 +/* 1680 +** Verify that pFrame is a valid VdbeFrame pointer. Return true if it is 1681 +** and false if something is wrong. 1682 +** 1683 +** This routine is intended for use inside of assert() statements only. 1684 +*/ 1685 +int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){ 1686 + if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0; 1687 + return 1; 1688 +} 1689 +#endif 1690 + 1691 + 1692 +/* 1693 +** This is a destructor on a Mem object (which is really an sqlite3_value) 1694 +** that deletes the Frame object that is attached to it as a blob. 1695 +** 1696 +** This routine does not delete the Frame right away. It merely adds the 1697 +** frame to a list of frames to be deleted when the Vdbe halts. 1698 +*/ 1699 +void sqlite3VdbeFrameMemDel(void *pArg){ 1700 + VdbeFrame *pFrame = (VdbeFrame*)pArg; 1701 + assert( sqlite3VdbeFrameIsValid(pFrame) ); 1702 + pFrame->pParent = pFrame->v->pDelFrame; 1703 + pFrame->v->pDelFrame = pFrame; 1704 +} 1705 + 1677 1706 1678 1707 /* 1679 1708 ** Delete a VdbeFrame object and its contents. VdbeFrame objects are 1680 1709 ** allocated by the OP_Program opcode in sqlite3VdbeExec(). 1681 1710 */ 1682 1711 void sqlite3VdbeFrameDelete(VdbeFrame *p){ 1683 1712 int i; 1684 1713 Mem *aMem = VdbeFrameMem(p); 1685 1714 VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem]; 1715 + assert( sqlite3VdbeFrameIsValid(p) ); 1686 1716 for(i=0; i<p->nChildCsr; i++){ 1687 1717 sqlite3VdbeFreeCursor(p->v, apCsr[i]); 1688 1718 } 1689 1719 releaseMemArray(aMem, p->nChildMem); 1690 1720 sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0); 1691 1721 sqlite3DbFree(p->v->db, p); 1692 1722 } ................................................................................ 3957 3987 int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ 3958 3988 int f1, f2; 3959 3989 int combined_flags; 3960 3990 3961 3991 f1 = pMem1->flags; 3962 3992 f2 = pMem2->flags; 3963 3993 combined_flags = f1|f2; 3964 - assert( (combined_flags & MEM_RowSet)==0 ); 3994 + assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) ); 3965 3995 3966 3996 /* If one value is NULL, it is less than the other. If both values 3967 3997 ** are NULL, return 0. 3968 3998 */ 3969 3999 if( combined_flags&MEM_Null ){ 3970 4000 return (f2&MEM_Null) - (f1&MEM_Null); 3971 4001 }
Changes to src/vdbemem.c.
38 38 assert( (p->flags & MEM_Dyn)==0 || p->szMalloc==0 ); 39 39 40 40 /* Cannot be both MEM_Int and MEM_Real at the same time */ 41 41 assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) ); 42 42 43 43 if( p->flags & MEM_Null ){ 44 44 /* Cannot be both MEM_Null and some other type */ 45 - assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob 46 - |MEM_RowSet|MEM_Frame|MEM_Agg))==0 ); 45 + assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 ); 47 46 48 47 /* If MEM_Null is set, then either the value is a pure NULL (the usual 49 48 ** case) or it is a pointer set using sqlite3_bind_pointer() or 50 49 ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be 51 50 ** set. 52 51 */ 53 52 if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){ ................................................................................ 152 151 ** SQLITE_NOMEM may be returned if a malloc() fails during conversion 153 152 ** between formats. 154 153 */ 155 154 int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ 156 155 #ifndef SQLITE_OMIT_UTF16 157 156 int rc; 158 157 #endif 159 - assert( (pMem->flags&MEM_RowSet)==0 ); 158 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 160 159 assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE 161 160 || desiredEnc==SQLITE_UTF16BE ); 162 161 if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ 163 162 return SQLITE_OK; 164 163 } 165 164 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 166 165 #ifdef SQLITE_OMIT_UTF16 ................................................................................ 185 184 ** If the bPreserve argument is true, then copy of the content of 186 185 ** pMem->z into the new allocation. pMem must be either a string or 187 186 ** blob if bPreserve is true. If bPreserve is false, any prior content 188 187 ** in pMem->z is discarded. 189 188 */ 190 189 SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){ 191 190 assert( sqlite3VdbeCheckMemInvariants(pMem) ); 192 - assert( (pMem->flags&MEM_RowSet)==0 ); 191 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 193 192 testcase( pMem->db==0 ); 194 193 195 194 /* If the bPreserve flag is set to true, then the memory cell must already 196 195 ** contain a valid string or blob value. */ 197 196 assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); 198 197 testcase( bPreserve && pMem->z==0 ); 199 198 ................................................................................ 273 272 ** Change pMem so that its MEM_Str or MEM_Blob value is stored in 274 273 ** MEM.zMalloc, where it can be safely written. 275 274 ** 276 275 ** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails. 277 276 */ 278 277 int sqlite3VdbeMemMakeWriteable(Mem *pMem){ 279 278 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 280 - assert( (pMem->flags&MEM_RowSet)==0 ); 279 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 281 280 if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){ 282 281 if( ExpandBlob(pMem) ) return SQLITE_NOMEM; 283 282 if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){ 284 283 int rc = vdbeMemAddTerminator(pMem); 285 284 if( rc ) return rc; 286 285 } 287 286 } ................................................................................ 298 297 ** blob stored in dynamically allocated space. 299 298 */ 300 299 #ifndef SQLITE_OMIT_INCRBLOB 301 300 int sqlite3VdbeMemExpandBlob(Mem *pMem){ 302 301 int nByte; 303 302 assert( pMem->flags & MEM_Zero ); 304 303 assert( pMem->flags&MEM_Blob ); 305 - assert( (pMem->flags&MEM_RowSet)==0 ); 304 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 306 305 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 307 306 308 307 /* Set nByte to the number of bytes required to store the expanded blob. */ 309 308 nByte = pMem->n + pMem->u.nZero; 310 309 if( nByte<=0 ){ 311 310 nByte = 1; 312 311 } ................................................................................ 353 352 int fg = pMem->flags; 354 353 const int nByte = 32; 355 354 356 355 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 357 356 assert( !(fg&MEM_Zero) ); 358 357 assert( !(fg&(MEM_Str|MEM_Blob)) ); 359 358 assert( fg&(MEM_Int|MEM_Real) ); 360 - assert( (pMem->flags&MEM_RowSet)==0 ); 359 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 361 360 assert( EIGHT_BYTE_ALIGNMENT(pMem) ); 362 361 363 362 364 363 if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ 365 364 pMem->enc = 0; 366 365 return SQLITE_NOMEM_BKPT; 367 366 } ................................................................................ 458 457 assert( VdbeMemDynamic(p) ); 459 458 if( p->flags&MEM_Agg ){ 460 459 sqlite3VdbeMemFinalize(p, p->u.pDef); 461 460 assert( (p->flags & MEM_Agg)==0 ); 462 461 testcase( p->flags & MEM_Dyn ); 463 462 } 464 463 if( p->flags&MEM_Dyn ){ 465 - assert( (p->flags&MEM_RowSet)==0 ); 466 464 assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 ); 467 465 p->xDel((void *)p->z); 468 - }else if( p->flags&MEM_RowSet ){ 469 - sqlite3RowSetClear(p->u.pRowSet); 470 - }else if( p->flags&MEM_Frame ){ 471 - VdbeFrame *pFrame = p->u.pFrame; 472 - pFrame->pParent = pFrame->v->pDelFrame; 473 - pFrame->v->pDelFrame = pFrame; 474 466 } 475 467 p->flags = MEM_Null; 476 468 } 477 469 478 470 /* 479 471 ** Release memory held by the Mem p, both external memory cleared 480 472 ** by p->xDel and memory in p->zMalloc. ................................................................................ 614 606 /* 615 607 ** The MEM structure is already a MEM_Real. Try to also make it a 616 608 ** MEM_Int if we can. 617 609 */ 618 610 void sqlite3VdbeIntegerAffinity(Mem *pMem){ 619 611 i64 ix; 620 612 assert( pMem->flags & MEM_Real ); 621 - assert( (pMem->flags & MEM_RowSet)==0 ); 613 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 622 614 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 623 615 assert( EIGHT_BYTE_ALIGNMENT(pMem) ); 624 616 625 617 ix = doubleToInt64(pMem->u.r); 626 618 627 619 /* Only mark the value as an integer if 628 620 ** ................................................................................ 641 633 } 642 634 643 635 /* 644 636 ** Convert pMem to type integer. Invalidate any prior representations. 645 637 */ 646 638 int sqlite3VdbeMemIntegerify(Mem *pMem){ 647 639 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 648 - assert( (pMem->flags & MEM_RowSet)==0 ); 640 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 649 641 assert( EIGHT_BYTE_ALIGNMENT(pMem) ); 650 642 651 643 pMem->u.i = sqlite3VdbeIntValue(pMem); 652 644 MemSetTypeFlag(pMem, MEM_Int); 653 645 return SQLITE_OK; 654 646 } 655 647 ................................................................................ 859 851 if( !sqlite3IsNaN(val) ){ 860 852 pMem->u.r = val; 861 853 pMem->flags = MEM_Real; 862 854 } 863 855 } 864 856 #endif 865 857 858 +#ifdef SQLITE_DEBUG 859 +/* 860 +** Return true if the Mem holds a RowSet object. This routine is intended 861 +** for use inside of assert() statements. 862 +*/ 863 +int sqlite3VdbeMemIsRowSet(const Mem *pMem){ 864 + return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn) 865 + && pMem->xDel==sqlite3RowSetDelete; 866 +} 867 +#endif 868 + 866 869 /* 867 870 ** Delete any previous value and set the value of pMem to be an 868 871 ** empty boolean index. 872 +** 873 +** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation 874 +** error occurs. 869 875 */ 870 -void sqlite3VdbeMemSetRowSet(Mem *pMem){ 876 +int sqlite3VdbeMemSetRowSet(Mem *pMem){ 871 877 sqlite3 *db = pMem->db; 878 + RowSet *p; 872 879 assert( db!=0 ); 873 - assert( (pMem->flags & MEM_RowSet)==0 ); 880 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 874 881 sqlite3VdbeMemRelease(pMem); 875 - pMem->zMalloc = sqlite3DbMallocRawNN(db, 64); 876 - if( db->mallocFailed ){ 877 - pMem->flags = MEM_Null; 878 - pMem->szMalloc = 0; 879 - }else{ 880 - assert( pMem->zMalloc ); 881 - pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc); 882 - pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc); 883 - assert( pMem->u.pRowSet!=0 ); 884 - pMem->flags = MEM_RowSet; 885 - } 882 + p = sqlite3RowSetInit(db); 883 + if( p==0 ) return SQLITE_NOMEM; 884 + pMem->z = (char*)p; 885 + pMem->flags = MEM_Blob|MEM_Dyn; 886 + pMem->xDel = sqlite3RowSetDelete; 887 + return SQLITE_OK; 886 888 } 887 889 888 890 /* 889 891 ** Return true if the Mem object contains a TEXT or BLOB that is 890 892 ** too large - whose size exceeds SQLITE_MAX_LENGTH. 891 893 */ 892 894 int sqlite3VdbeMemTooBig(Mem *p){ ................................................................................ 946 948 */ 947 949 static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){ 948 950 vdbeMemClearExternAndSetNull(pTo); 949 951 assert( !VdbeMemDynamic(pTo) ); 950 952 sqlite3VdbeMemShallowCopy(pTo, pFrom, eType); 951 953 } 952 954 void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){ 953 - assert( (pFrom->flags & MEM_RowSet)==0 ); 955 + assert( !sqlite3VdbeMemIsRowSet(pFrom) ); 954 956 assert( pTo->db==pFrom->db ); 955 957 if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; } 956 958 memcpy(pTo, pFrom, MEMCELLSIZE); 957 959 if( (pFrom->flags&MEM_Static)==0 ){ 958 960 pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem); 959 961 assert( srcType==MEM_Ephem || srcType==MEM_Static ); 960 962 pTo->flags |= srcType; ................................................................................ 964 966 /* 965 967 ** Make a full copy of pFrom into pTo. Prior contents of pTo are 966 968 ** freed before the copy is made. 967 969 */ 968 970 int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ 969 971 int rc = SQLITE_OK; 970 972 971 - assert( (pFrom->flags & MEM_RowSet)==0 ); 973 + assert( !sqlite3VdbeMemIsRowSet(pFrom) ); 972 974 if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo); 973 975 memcpy(pTo, pFrom, MEMCELLSIZE); 974 976 pTo->flags &= ~MEM_Dyn; 975 977 if( pTo->flags&(MEM_Str|MEM_Blob) ){ 976 978 if( 0==(pFrom->flags&MEM_Static) ){ 977 979 pTo->flags |= MEM_Ephem; 978 980 rc = sqlite3VdbeMemMakeWriteable(pTo); ................................................................................ 1022 1024 void (*xDel)(void*) /* Destructor function */ 1023 1025 ){ 1024 1026 int nByte = n; /* New value for pMem->n */ 1025 1027 int iLimit; /* Maximum allowed string or blob size */ 1026 1028 u16 flags = 0; /* New value for pMem->flags */ 1027 1029 1028 1030 assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); 1029 - assert( (pMem->flags & MEM_RowSet)==0 ); 1031 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 1030 1032 1031 1033 /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ 1032 1034 if( !z ){ 1033 1035 sqlite3VdbeMemSetNull(pMem); 1034 1036 return SQLITE_OK; 1035 1037 } 1036 1038 ................................................................................ 1144 1146 int rc = SQLITE_OK; /* Return code */ 1145 1147 1146 1148 assert( sqlite3BtreeCursorIsValid(pCur) ); 1147 1149 assert( !VdbeMemDynamic(pMem) ); 1148 1150 1149 1151 /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert() 1150 1152 ** that both the BtShared and database handle mutexes are held. */ 1151 - assert( (pMem->flags & MEM_RowSet)==0 ); 1153 + assert( !sqlite3VdbeMemIsRowSet(pMem) ); 1152 1154 zData = (char *)sqlite3BtreePayloadFetch(pCur, &available); 1153 1155 assert( zData!=0 ); 1154 1156 1155 1157 if( offset+amt<=available ){ 1156 1158 pMem->z = &zData[offset]; 1157 1159 pMem->flags = MEM_Blob|MEM_Ephem; 1158 1160 pMem->n = (int)amt; ................................................................................ 1168 1170 ** Convert it into a string with encoding enc and return a pointer 1169 1171 ** to a zero-terminated version of that string. 1170 1172 */ 1171 1173 static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ 1172 1174 assert( pVal!=0 ); 1173 1175 assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); 1174 1176 assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); 1175 - assert( (pVal->flags & MEM_RowSet)==0 ); 1177 + assert( !sqlite3VdbeMemIsRowSet(pVal) ); 1176 1178 assert( (pVal->flags & (MEM_Null))==0 ); 1177 1179 if( pVal->flags & (MEM_Blob|MEM_Str) ){ 1178 1180 if( ExpandBlob(pVal) ) return 0; 1179 1181 pVal->flags |= MEM_Str; 1180 1182 if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){ 1181 1183 sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED); 1182 1184 } ................................................................................ 1211 1213 ** If that is the case, then the result must be aligned on an even byte 1212 1214 ** boundary. 1213 1215 */ 1214 1216 const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ 1215 1217 if( !pVal ) return 0; 1216 1218 assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) ); 1217 1219 assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); 1218 - assert( (pVal->flags & MEM_RowSet)==0 ); 1220 + assert( !sqlite3VdbeMemIsRowSet(pVal) ); 1219 1221 if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ 1220 1222 assert( sqlite3VdbeMemConsistentDualRep(pVal) ); 1221 1223 return pVal->z; 1222 1224 } 1223 1225 if( pVal->flags&MEM_Null ){ 1224 1226 return 0; 1225 1227 }
Changes to src/vdbesort.c.
2103 2103 static int vdbeMergeEngineInit( 2104 2104 SortSubtask *pTask, /* Thread that will run pMerger */ 2105 2105 MergeEngine *pMerger, /* MergeEngine to initialize */ 2106 2106 int eMode /* One of the INCRINIT_XXX constants */ 2107 2107 ){ 2108 2108 int rc = SQLITE_OK; /* Return code */ 2109 2109 int i; /* For looping over PmaReader objects */ 2110 - int nTree = pMerger->nTree; 2110 + int nTree; /* Number of subtrees to merge */ 2111 + 2112 + /* Failure to allocate the merge would have been detected prior to 2113 + ** invoking this routine */ 2114 + assert( pMerger!=0 ); 2111 2115 2112 2116 /* eMode is always INCRINIT_NORMAL in single-threaded mode */ 2113 2117 assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); 2114 2118 2115 2119 /* Verify that the MergeEngine is assigned to a single thread */ 2116 2120 assert( pMerger->pTask==0 ); 2117 2121 pMerger->pTask = pTask; 2118 2122 2123 + nTree = pMerger->nTree; 2119 2124 for(i=0; i<nTree; i++){ 2120 2125 if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){ 2121 2126 /* PmaReaders should be normally initialized in order, as if they are 2122 2127 ** reading from the same temp file this makes for more linear file IO. 2123 2128 ** However, in the INCRINIT_ROOT case, if PmaReader aReadr[nTask-1] is 2124 2129 ** in use it will block the vdbePmaReaderNext() call while it uses 2125 2130 ** the main thread to fill its buffer. So calling PmaReaderNext()
Changes to src/wal.c.
254 254 #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) 255 255 int sqlite3WalTrace = 0; 256 256 # define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X 257 257 #else 258 258 # define WALTRACE(X) 259 259 #endif 260 260 261 +/* 262 +** WAL mode depends on atomic aligned 32-bit loads and stores in a few 263 +** places. The following macros try to make this explicit. 264 +*/ 265 +#if GCC_VESRION>=5004000 266 +# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) 267 +# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED) 268 +#else 269 +# define AtomicLoad(PTR) (*(PTR)) 270 +# define AtomicStore(PTR,VAL) (*(PTR) = (VAL)) 271 +#endif 272 + 261 273 /* 262 274 ** The maximum (and only) versions of the wal and wal-index formats 263 275 ** that may be interpreted by this version of SQLite. 264 276 ** 265 277 ** If a client begins recovering a WAL file and finds that (a) the checksum 266 278 ** values in the wal-header are correct and (b) the version field is not 267 279 ** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. ................................................................................ 2551 2563 mxFrame = pWal->hdr.mxFrame; 2552 2564 #ifdef SQLITE_ENABLE_SNAPSHOT 2553 2565 if( pWal->pSnapshot && pWal->pSnapshot->mxFrame<mxFrame ){ 2554 2566 mxFrame = pWal->pSnapshot->mxFrame; 2555 2567 } 2556 2568 #endif 2557 2569 for(i=1; i<WAL_NREADER; i++){ 2558 - u32 thisMark = pInfo->aReadMark[i]; 2570 + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); 2559 2571 if( mxReadMark<=thisMark && thisMark<=mxFrame ){ 2560 2572 assert( thisMark!=READMARK_NOT_USED ); 2561 2573 mxReadMark = thisMark; 2562 2574 mxI = i; 2563 2575 } 2564 2576 } 2565 2577 if( (pWal->readOnly & WAL_SHM_RDONLY)==0 2566 2578 && (mxReadMark<mxFrame || mxI==0) 2567 2579 ){ 2568 2580 for(i=1; i<WAL_NREADER; i++){ 2569 2581 rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1); 2570 2582 if( rc==SQLITE_OK ){ 2571 - mxReadMark = pInfo->aReadMark[i] = mxFrame; 2583 + mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame); 2572 2584 mxI = i; 2573 2585 walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); 2574 2586 break; 2575 2587 }else if( rc!=SQLITE_BUSY ){ 2576 2588 return rc; 2577 2589 } 2578 2590 } ................................................................................ 2616 2628 ** A) on the basis that there is a newer version (version B) of the same 2617 2629 ** page later in the wal file. But if version B happens to like past 2618 2630 ** frame pWal->hdr.mxFrame - then the client would incorrectly assume 2619 2631 ** that it can read version A from the database file. However, since 2620 2632 ** we can guarantee that the checkpointer that set nBackfill could not 2621 2633 ** see any pages past pWal->hdr.mxFrame, this problem does not come up. 2622 2634 */ 2623 - pWal->minFrame = pInfo->nBackfill+1; 2635 + pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; 2624 2636 walShmBarrier(pWal); 2625 - if( pInfo->aReadMark[mxI]!=mxReadMark 2637 + if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark 2626 2638 || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) 2627 2639 ){ 2628 2640 walUnlockShared(pWal, WAL_READ_LOCK(mxI)); 2629 2641 return WAL_RETRY; 2630 2642 }else{ 2631 2643 assert( mxReadMark<=pWal->hdr.mxFrame ); 2632 2644 pWal->readLock = (i16)mxI; ................................................................................ 2779 2791 */ 2780 2792 rc = walLockShared(pWal, WAL_CKPT_LOCK); 2781 2793 2782 2794 if( rc==SQLITE_OK ){ 2783 2795 /* Check that the wal file has not been wrapped. Assuming that it has 2784 2796 ** not, also check that no checkpointer has attempted to checkpoint any 2785 2797 ** frames beyond pSnapshot->mxFrame. If either of these conditions are 2786 - ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr 2798 + ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr 2787 2799 ** with *pSnapshot and set *pChanged as appropriate for opening the 2788 2800 ** snapshot. */ 2789 2801 if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) 2790 2802 && pSnapshot->mxFrame>=pInfo->nBackfillAttempted 2791 2803 ){ 2792 2804 assert( pWal->readLock>0 ); 2793 2805 memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); 2794 2806 *pChanged = bChanged; 2795 2807 }else{ 2796 - rc = SQLITE_BUSY_SNAPSHOT; 2808 + rc = SQLITE_ERROR_SNAPSHOT; 2797 2809 } 2798 2810 2799 2811 /* Release the shared CKPT lock obtained above. */ 2800 2812 walUnlockShared(pWal, WAL_CKPT_LOCK); 2813 + pWal->minFrame = 1; 2801 2814 } 2802 2815 2803 2816 2804 2817 if( rc!=SQLITE_OK ){ 2805 2818 sqlite3WalEndReadTransaction(pWal); 2806 2819 } 2807 2820 } ................................................................................ 3785 3798 int rc; 3786 3799 rc = walLockShared(pWal, WAL_CKPT_LOCK); 3787 3800 if( rc==SQLITE_OK ){ 3788 3801 WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; 3789 3802 if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) 3790 3803 || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted 3791 3804 ){ 3792 - rc = SQLITE_BUSY_SNAPSHOT; 3805 + rc = SQLITE_ERROR_SNAPSHOT; 3793 3806 walUnlockShared(pWal, WAL_CKPT_LOCK); 3794 3807 } 3795 3808 } 3796 3809 return rc; 3797 3810 } 3798 3811 3799 3812 /*
Changes to src/whereexpr.c.
336 336 ** appropriate virtual table operator. The return value is 1 or 2 if there 337 337 ** is a match. The usual return is 1, but if the RHS is also a column 338 338 ** of virtual table in forms (5) or (7) then return 2. 339 339 ** 340 340 ** If the expression matches none of the patterns above, return 0. 341 341 */ 342 342 static int isAuxiliaryVtabOperator( 343 + sqlite3 *db, /* Parsing context */ 343 344 Expr *pExpr, /* Test this expression */ 344 345 unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ 345 346 Expr **ppLeft, /* Column expression to left of MATCH/op2 */ 346 347 Expr **ppRight /* Expression to left of MATCH/op2 */ 347 348 ){ 348 349 if( pExpr->op==TK_FUNCTION ){ 349 350 static const struct Op2 { ................................................................................ 359 360 Expr *pCol; /* Column reference */ 360 361 int i; 361 362 362 363 pList = pExpr->x.pList; 363 364 if( pList==0 || pList->nExpr!=2 ){ 364 365 return 0; 365 366 } 367 + 368 + /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a 369 + ** virtual table on their second argument, which is the same as 370 + ** the left-hand side operand in their in-fix form. 371 + ** 372 + ** vtab_column MATCH expression 373 + ** MATCH(expression,vtab_column) 374 + */ 366 375 pCol = pList->a[1].pExpr; 367 - if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ 368 - return 0; 376 + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ 377 + for(i=0; i<ArraySize(aOp); i++){ 378 + if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ 379 + *peOp2 = aOp[i].eOp2; 380 + *ppRight = pList->a[0].pExpr; 381 + *ppLeft = pCol; 382 + return 1; 383 + } 384 + } 369 385 } 370 - for(i=0; i<ArraySize(aOp); i++){ 371 - if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ 372 - *peOp2 = aOp[i].eOp2; 373 - *ppRight = pList->a[0].pExpr; 374 - *ppLeft = pCol; 375 - return 1; 386 + 387 + /* We can also match against the first column of overloaded 388 + ** functions where xFindFunction returns a value of at least 389 + ** SQLITE_INDEX_CONSTRAINT_FUNCTION. 390 + ** 391 + ** OVERLOADED(vtab_column,expression) 392 + ** 393 + ** Historically, xFindFunction expected to see lower-case function 394 + ** names. But for this use case, xFindFunction is expected to deal 395 + ** with function names in an arbitrary case. 396 + */ 397 + pCol = pList->a[0].pExpr; 398 + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ 399 + sqlite3_vtab *pVtab; 400 + sqlite3_module *pMod; 401 + void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); 402 + void *pNotUsed; 403 + pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; 404 + assert( pVtab!=0 ); 405 + assert( pVtab->pModule!=0 ); 406 + pMod = (sqlite3_module *)pVtab->pModule; 407 + if( pMod->xFindFunction!=0 ){ 408 + i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); 409 + if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ 410 + *peOp2 = i; 411 + *ppRight = pList->a[1].pExpr; 412 + *ppLeft = pCol; 413 + return 1; 414 + } 376 415 } 377 416 } 378 417 }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ 379 418 int res = 0; 380 419 Expr *pLeft = pExpr->pLeft; 381 420 Expr *pRight = pExpr->pRight; 382 421 if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ ................................................................................ 816 855 int idxNew; 817 856 transferJoinMarkings(pNew, pExpr); 818 857 assert( !ExprHasProperty(pNew, EP_xIsSelect) ); 819 858 pNew->x.pList = pList; 820 859 idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); 821 860 testcase( idxNew==0 ); 822 861 exprAnalyze(pSrc, pWC, idxNew); 823 - pTerm = &pWC->a[idxTerm]; 862 + /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */ 824 863 markTermAsChild(pWC, idxNew, idxTerm); 825 864 }else{ 826 865 sqlite3ExprListDelete(db, pList); 827 866 } 828 867 } 829 868 } 830 869 } ................................................................................ 1233 1272 ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL. 1234 1273 ** This information is used by the xBestIndex methods of 1235 1274 ** virtual tables. The native query optimizer does not attempt 1236 1275 ** to do anything with MATCH functions. 1237 1276 */ 1238 1277 if( pWC->op==TK_AND ){ 1239 1278 Expr *pRight = 0, *pLeft = 0; 1240 - int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); 1279 + int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); 1241 1280 while( res-- > 0 ){ 1242 1281 int idxNew; 1243 1282 WhereTerm *pNewTerm; 1244 1283 Bitmask prereqColumn, prereqExpr; 1245 1284 1246 1285 prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight); 1247 1286 prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
Changes to test/alter.test.
677 677 do_test alter-8.2 { 678 678 execsql { 679 679 SELECT a, sum(b) FROM t2 GROUP BY a; 680 680 } 681 681 } {1 18 2 9} 682 682 683 683 #-------------------------------------------------------------------------- 684 -# alter-9.X - Special test: Make sure the sqlite_rename_trigger() and 684 +# alter-9.X - Special test: Make sure the sqlite_rename_column() and 685 685 # rename_table() functions do not crash when handed bad input. 686 686 # 687 -ifcapable trigger { 688 - do_test alter-9.1 { 689 - execsql {SELECT SQLITE_RENAME_TRIGGER(0,0)} 690 - } {{}} 687 +do_test alter-9.1 { 688 + execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0)} 689 +} {{}} 690 +foreach {tn sql} { 691 + 1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0) } 692 + 2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50) } 693 + 3 { SELECT SQLITE_RENAME_TABLE('foo', 'foo', 'foo', 'foo', 'foo') } 694 +} { 695 + do_catchsql_test alter-9.2.$tn $sql {1 {SQL logic error}} 691 696 } 692 -do_test alter-9.2 { 693 - execsql { 694 - SELECT SQLITE_RENAME_TABLE(0,0); 695 - SELECT SQLITE_RENAME_TABLE(10,20); 696 - SELECT SQLITE_RENAME_TABLE('foo', 'foo'); 697 - } 698 -} {{} {} {}} 699 697 700 698 #------------------------------------------------------------------------ 701 699 # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters 702 700 # in the names. 703 701 # 704 702 do_test alter-10.1 { 705 703 execsql "CREATE TABLE xyz(x UNIQUE)" ................................................................................ 871 869 SELECT * FROM t16a ORDER BY a; 872 870 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} 873 871 do_execsql_test alter-16.2 { 874 872 ALTER TABLE t16a RENAME TO t16a_rn; 875 873 SELECT * FROM t16a_rn ORDER BY a; 876 874 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle} 877 875 878 -#------------------------------------------------------------------------- 879 -# Verify that NULL values into the internal-use-only sqlite_rename_*() 880 -# functions do not cause problems. 881 -# 882 -do_execsql_test alter-17.1 { 883 - SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc'); 884 -} {{CREATE TABLE "abc"(a,b,c)}} 885 -do_execsql_test alter-17.2 { 886 - SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL); 887 -} {{CREATE TABLE "(NULL)"(a,b,c)}} 888 -do_execsql_test alter-17.3 { 889 - SELECT sqlite_rename_table(NULL,'abc'); 890 -} {{}} 891 -do_execsql_test alter-17.4 { 892 - SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc'); 893 -} {{CREATE TRIGGER r1 ON "abc" WHEN}} 894 -do_execsql_test alter-17.5 { 895 - SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL); 896 -} {{CREATE TRIGGER r1 ON "(NULL)" WHEN}} 897 -do_execsql_test alter-17.6 { 898 - SELECT sqlite_rename_trigger(NULL,'abc'); 899 -} {{}} 900 -do_execsql_test alter-17.7 { 901 - SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', 902 - 'xyzzy','lmnop'); 903 -} {{CREATE TABLE t1(a REFERENCES "lmnop")}} 904 -do_execsql_test alter-17.8 { 905 - SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', 906 - 'xyzzy',NULL); 907 -} {{CREATE TABLE t1(a REFERENCES "(NULL)")}} 908 -do_execsql_test alter-17.9 { 909 - SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")', 910 - NULL, 'lmnop'); 911 -} {{}} 912 -do_execsql_test alter-17.10 { 913 - SELECT sqlite_rename_parent(NULL,'abc','xyz'); 914 -} {{}} 915 -do_execsql_test alter-17.11 { 916 - SELECT sqlite_rename_parent('create references ''','abc','xyz'); 917 -} {{create references '}} 918 -do_execsql_test alter-17.12 { 919 - SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz'); 920 -} {{create references "xyz"123" }} 921 -do_execsql_test alter-17.13 { 922 - SELECT sqlite_rename_parent("references '''",'abc','xyz'); 923 -} {{references '''}} 924 - 925 876 finish_test 877 +
Changes to test/altercol.test.
650 650 651 651 do_execsql_test 15.2 { 652 652 SELECT sql FROM sqlite_master WHERE type='view'; 653 653 } {{CREATE VIEW vvv AS SELECT xyz AS d FROM xxx WHERE d=0}} 654 654 655 655 #------------------------------------------------------------------------- 656 656 # 657 -do_execsql_test 16.0 { 657 +do_execsql_test 16.1.0 { 658 658 CREATE TABLE t1(a,b,c); 659 659 CREATE TABLE t2(d,e,f); 660 660 INSERT INTO t1 VALUES(1,2,3); 661 661 INSERT INTO t2 VALUES(4,5,6); 662 662 CREATE VIEW v4 AS SELECT a, d FROM t1, t2; 663 663 SELECT * FROM v4; 664 664 } {1 4} 665 665 666 -do_catchsql_test 16.1 { 666 +do_catchsql_test 16.1.1 { 667 667 ALTER TABLE t2 RENAME d TO a; 668 668 } {1 {error in view v4 after rename: ambiguous column name: a}} 669 669 670 -do_execsql_test 16.2 { 670 +do_execsql_test 16.1.2 { 671 671 SELECT * FROM v4; 672 672 } {1 4} 673 673 674 -do_execsql_test 16.3 { 674 +do_execsql_test 16.1.3 { 675 675 CREATE UNIQUE INDEX t2d ON t2(d); 676 676 CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 677 677 INSERT INTO t2 VALUES(new.a, new.b, new.c) 678 678 ON CONFLICT(d) DO UPDATE SET f = excluded.f; 679 679 END; 680 680 } 681 681 682 -do_execsql_test 16.4 { 682 +do_execsql_test 16.1.4 { 683 683 INSERT INTO t1 VALUES(4, 8, 456); 684 684 SELECT * FROM t2; 685 685 } {4 5 456} 686 686 687 -do_execsql_test 16.5 { 687 +do_execsql_test 16.1.5 { 688 688 ALTER TABLE t2 RENAME COLUMN f TO "big f"; 689 689 INSERT INTO t1 VALUES(4, 0, 20456); 690 690 SELECT * FROM t2; 691 691 } {4 5 20456} 692 692 693 -do_execsql_test 16.6 { 693 +do_execsql_test 16.1.6 { 694 694 ALTER TABLE t1 RENAME COLUMN c TO "big c"; 695 695 INSERT INTO t1 VALUES(4, 0, 0); 696 696 SELECT * FROM t2; 697 697 } {4 5 0} 698 + 699 +do_execsql_test 16.2.1 { 700 + CREATE VIEW temp.v5 AS SELECT "big c" FROM t1; 701 + SELECT * FROM v5; 702 +} {3 456 20456 0} 703 + 704 +do_execsql_test 16.2.2 { 705 + ALTER TABLE t1 RENAME COLUMN "big c" TO reallybigc; 706 +} {} 707 + 708 +do_execsql_test 16.2.3 { 709 + SELECT * FROM v5; 710 +} {3 456 20456 0} 698 711 699 712 finish_test
Added test/altertab.test.
1 +# 2018 August 24 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#************************************************************************* 11 +# 12 + 13 +set testdir [file dirname $argv0] 14 +source $testdir/tester.tcl 15 +set testprefix altertab 16 + 17 +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. 18 +ifcapable !altertable { 19 + finish_test 20 + return 21 +} 22 + 23 +do_execsql_test 1.0 { 24 + CREATE TABLE t1(a, b, CHECK(t1.a != t1.b)); 25 + 26 + CREATE TABLE t2(a, b); 27 + CREATE INDEX t2expr ON t2(a) WHERE t2.b>0; 28 +} 29 + 30 +do_execsql_test 1.1 { 31 + SELECT sql FROM sqlite_master 32 +} { 33 + {CREATE TABLE t1(a, b, CHECK(t1.a != t1.b))} 34 + {CREATE TABLE t2(a, b)} 35 + {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} 36 +} 37 + 38 +do_execsql_test 1.2 { 39 + ALTER TABLE t1 RENAME TO t1new; 40 +} 41 + 42 +do_execsql_test 1.3 { 43 + CREATE TABLE t3(c, d); 44 + ALTER TABLE t3 RENAME TO t3new; 45 + DROP TABLE t3new; 46 +} 47 + 48 +do_execsql_test 1.4 { 49 + SELECT sql FROM sqlite_master 50 +} { 51 + {CREATE TABLE "t1new"(a, b, CHECK("t1new".a != "t1new".b))} 52 + {CREATE TABLE t2(a, b)} 53 + {CREATE INDEX t2expr ON t2(a) WHERE t2.b>0} 54 +} 55 + 56 + 57 +do_execsql_test 1.3 { 58 + ALTER TABLE t2 RENAME TO t2new; 59 +} 60 +do_execsql_test 1.4 { 61 + SELECT sql FROM sqlite_master 62 +} { 63 + {CREATE TABLE "t1new"(a, b, CHECK("t1new".a != "t1new".b))} 64 + {CREATE TABLE "t2new"(a, b)} 65 + {CREATE INDEX t2expr ON "t2new"(a) WHERE "t2new".b>0} 66 +} 67 + 68 + 69 +#------------------------------------------------------------------------- 70 +reset_db 71 +register_echo_module db 72 + 73 +do_execsql_test 2.0 { 74 + CREATE TABLE abc(a, b, c); 75 + INSERT INTO abc VALUES(1, 2, 3); 76 + CREATE VIRTUAL TABLE eee USING echo('abc'); 77 + SELECT * FROM eee; 78 +} {1 2 3} 79 + 80 +do_execsql_test 2.1 { 81 + ALTER TABLE eee RENAME TO fff; 82 + SELECT * FROM fff; 83 +} {1 2 3} 84 + 85 +db close 86 +sqlite3 db test.db 87 + 88 +do_catchsql_test 2.2 { 89 + ALTER TABLE fff RENAME TO ggg; 90 +} {1 {no such module: echo}} 91 + 92 +#------------------------------------------------------------------------- 93 +reset_db 94 + 95 +do_execsql_test 3.0 { 96 + CREATE TABLE txx(a, b, c); 97 + INSERT INTO txx VALUES(1, 2, 3); 98 + CREATE VIEW vvv AS SELECT main.txx.a, txx.b, c FROM txx; 99 + CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM txx AS one; 100 + CREATE VIEW temp.ttt AS SELECT main.txx.a, txx.b, one.b, main.one.a FROM txx AS one, txx; 101 +} 102 + 103 +do_execsql_test 3.1.1 { 104 + SELECT * FROM vvv; 105 +} {1 2 3} 106 +do_execsql_test 3.1.2 { 107 + ALTER TABLE txx RENAME TO "t xx"; 108 + SELECT * FROM vvv; 109 +} {1 2 3} 110 +do_execsql_test 3.1.3 { 111 + SELECT sql FROM sqlite_master WHERE name='vvv'; 112 +} {{CREATE VIEW vvv AS SELECT main."t xx".a, "t xx".b, c FROM "t xx"}} 113 + 114 + 115 +do_execsql_test 3.2.1 { 116 + SELECT * FROM uuu; 117 +} {1 2 3} 118 +do_execsql_test 3.2.2 { 119 + SELECT sql FROM sqlite_master WHERE name='uuu';; 120 +} {{CREATE VIEW uuu AS SELECT main.one.a, one.b, c FROM "t xx" AS one}} 121 + 122 +do_execsql_test 3.3.1 { 123 + SELECT * FROM ttt; 124 +} {1 2 2 1} 125 +do_execsql_test 3.3.2 { 126 + SELECT sql FROM sqlite_temp_master WHERE name='ttt'; 127 +} {{CREATE VIEW ttt AS SELECT main."t xx".a, "t xx".b, one.b, main.one.a FROM "t xx" AS one, "t xx"}} 128 + 129 +#------------------------------------------------------------------------- 130 +reset_db 131 +do_execsql_test 4.0 { 132 + CREATE table t1(x, y); 133 + CREATE table t2(a, b); 134 + 135 + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN 136 + SELECT t1.x, * FROM t1, t2; 137 + INSERT INTO t2 VALUES(new.x, new.y); 138 + END; 139 +} 140 + 141 +do_execsql_test 4.1 { 142 + INSERT INTO t1 VALUES(1, 1); 143 + ALTER TABLE t1 RENAME TO t11; 144 + INSERT INTO t11 VALUES(2, 2); 145 + ALTER TABLE t2 RENAME TO t22; 146 + INSERT INTO t11 VALUES(3, 3); 147 +} 148 + 149 +proc squish {a} { 150 + string trim [regsub -all {[[:space:]][[:space:]]*} $a { }] 151 +} 152 +db func squish squish 153 +do_test 4.2 { 154 + execsql { SELECT squish(sql) FROM sqlite_master WHERE name = 'tr1' } 155 +} [list [squish { 156 + CREATE TRIGGER tr1 AFTER INSERT ON "t11" BEGIN 157 + SELECT "t11".x, * FROM "t11", "t22"; 158 + INSERT INTO "t22" VALUES(new.x, new.y); 159 + END 160 +}]] 161 + 162 +#------------------------------------------------------------------------- 163 +reset_db 164 +do_execsql_test 5.0 { 165 + CREATE TABLE t9(a, b, c); 166 + CREATE TABLE t10(a, b, c); 167 + CREATE TEMP TABLE t9(a, b, c); 168 + 169 + CREATE TRIGGER temp.t9t AFTER INSERT ON temp.t9 BEGIN 170 + INSERT INTO t10 VALUES(new.a, new.b, new.c); 171 + END; 172 + 173 + INSERT INTO temp.t9 VALUES(1, 2, 3); 174 + SELECT * FROM t10; 175 +} {1 2 3} 176 + 177 +do_execsql_test 5.1 { 178 + ALTER TABLE temp.t9 RENAME TO 't1234567890' 179 +} 180 + 181 +do_execsql_test 5.2 { 182 + CREATE TABLE t1(a, b); 183 + CREATE TABLE t2(a, b); 184 + INSERT INTO t1 VALUES(1, 2); 185 + INSERT INTO t2 VALUES(3, 4); 186 + CREATE VIEW v AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2; 187 + SELECT * FROM v; 188 +} {1 2 3 4} 189 + 190 +do_catchsql_test 5.3 { 191 + ALTER TABLE t2 RENAME TO one; 192 +} {1 {error in view v after rename: ambiguous column name: one.a}} 193 + 194 +do_execsql_test 5.4 { 195 + SELECT * FROM v 196 +} {1 2 3 4} 197 + 198 +do_execsql_test 5.5 { 199 + DROP VIEW v; 200 + CREATE VIEW temp.vv AS SELECT one.a, one.b, t2.a, t2.b FROM t1 AS one, t2; 201 + SELECT * FROM vv; 202 +} {1 2 3 4} 203 + 204 +do_catchsql_test 5.6 { 205 + ALTER TABLE t2 RENAME TO one; 206 +} {1 {error in view vv after rename: ambiguous column name: one.a}} 207 + 208 +finish_test 209 + 210 +
Changes to test/fkey2.test.
979 979 } 980 980 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} 981 981 982 982 983 983 # Test the sqlite_rename_parent() function directly. 984 984 # 985 985 proc test_rename_parent {zCreate zOld zNew} { 986 - db eval {SELECT sqlite_rename_parent($zCreate, $zOld, $zNew)} 986 + db eval {SELECT sqlite_rename_table('main', $zCreate, $zOld, $zNew, 0)} 987 987 } 988 988 do_test fkey2-14.2.1.1 { 989 989 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 990 990 } {{CREATE TABLE t1(a REFERENCES "t3")}} 991 991 do_test fkey2-14.2.1.2 { 992 992 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 993 993 } {{CREATE TABLE t1(a REFERENCES t2)}}
Changes to test/server1.test.
21 21 22 22 # Skip this whole file if the server testing code is not enabled 23 23 # 24 24 if {[llength [info command client_step]]==0 || [sqlite3 -has-codec]} { 25 25 finish_test 26 26 return 27 27 } 28 + 29 +# This test does not work on older PPC Macs due to problems in the 30 +# pthreads library. So skip it. 31 +# 32 +if {$tcl_platform(machine)=="Power Macintosh" && 33 + $tcl_platform(byteOrder)=="bigEndian"} { 34 + finish_test 35 + return 36 +} 28 37 29 38 # The sample server implementation does not work right when memory 30 39 # management is enabled. 31 40 # 32 41 ifcapable (memorymanage||mutex_noop) { 33 42 finish_test 34 43 return
Changes to test/snapshot.test.
254 254 255 255 do_test $tn.$tn.3.3.2 { 256 256 snapshot_free $snapshot 257 257 execsql COMMIT 258 258 } {} 259 259 260 260 #------------------------------------------------------------------------- 261 - # Check that SQLITE_BUSY_SNAPSHOT is returned if the specified snapshot 261 + # Check that SQLITE_ERROR_SNAPSHOT is returned if the specified snapshot 262 262 # no longer exists because the wal file has been checkpointed. 263 263 # 264 264 # 1. Reading a snapshot from the middle of a wal file is not possible 265 265 # after the wal file has been checkpointed. 266 266 # 267 267 # 2. That a snapshot from the end of a wal file can not be read once 268 268 # the wal file has been wrapped. ................................................................................ 292 292 do_test $tn.4.1.3 { 293 293 execsql { 294 294 COMMIT; 295 295 PRAGMA wal_checkpoint; 296 296 BEGIN; 297 297 } 298 298 list [catch {snapshot_open db main $snapshot} msg] $msg 299 - } {1 SQLITE_BUSY_SNAPSHOT} 299 + } {1 SQLITE_ERROR_SNAPSHOT} 300 300 do_test $tn.4.1.4 { 301 301 snapshot_free $snapshot 302 302 execsql COMMIT 303 303 } {} 304 304 305 305 do_test $tn.4.2.1 { 306 306 execsql { ................................................................................ 323 323 do_test $tn.4.2.3 { 324 324 execsql { 325 325 COMMIT; 326 326 INSERT INTO t3 VALUES('e', 't'); 327 327 BEGIN; 328 328 } 329 329 list [catch {snapshot_open db main $snapshot} msg] $msg 330 - } {1 SQLITE_BUSY_SNAPSHOT} 330 + } {1 SQLITE_ERROR_SNAPSHOT} 331 331 do_test $tn.4.2.4 { 332 332 snapshot_free $snapshot 333 333 } {} 334 334 335 335 #------------------------------------------------------------------------- 336 336 # Check that SQLITE_BUSY is returned if a checkpoint is running when 337 337 # sqlite3_snapshot_open() is called.
Changes to test/snapshot2.test.
106 106 sqlite3_db_config db NO_CKPT_ON_CLOSE 1 107 107 db close 108 108 sqlite3 db test.db 109 109 110 110 execsql {SELECT * FROM sqlite_master} 111 111 execsql BEGIN 112 112 list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 113 -} {1 SQLITE_BUSY_SNAPSHOT} 113 +} {1 SQLITE_ERROR_SNAPSHOT} 114 114 115 115 do_test 2.3 { 116 116 execsql COMMIT 117 117 sqlite3_snapshot_recover db main 118 118 execsql BEGIN 119 119 sqlite3_snapshot_open_blob db main $snap 120 120 execsql { SELECT * FROM t1 } ................................................................................ 130 130 sqlite3_db_config db NO_CKPT_ON_CLOSE 1 131 131 db close 132 132 sqlite3 db test.db 133 133 134 134 sqlite3_snapshot_recover db main 135 135 execsql BEGIN 136 136 list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg 137 -} {1 SQLITE_BUSY_SNAPSHOT} 137 +} {1 SQLITE_ERROR_SNAPSHOT} 138 138 139 139 #------------------------------------------------------------------------- 140 140 # Check that calling sqlite3_snapshot_recover() does not confuse the 141 141 # pager cache. 142 142 reset_db 143 143 do_execsql_test 3.0 { 144 144 PRAGMA journal_mode = wal; ................................................................................ 230 230 db2 eval { SELECT * FROM t2 ; END } 231 231 } {abc def ghi} 232 232 233 233 do_test 5.4 { 234 234 execsql { INSERT INTO t2 VALUES('jkl') } 235 235 execsql BEGIN db2 236 236 list [catch { sqlite3_snapshot_open_blob db2 main $snap } msg] $msg 237 -} {1 SQLITE_BUSY_SNAPSHOT} 237 +} {1 SQLITE_ERROR_SNAPSHOT} 238 238 239 239 240 240 finish_test 241 241
Changes to test/snapshot3.test.
90 90 execsql { PRAGMA wal_checkpoint = truncate } 91 91 file size test.db-wal 92 92 } 0 93 93 94 94 do_test 1.8 { 95 95 execsql BEGIN db3 96 96 list [catch { sqlite3_snapshot_open_blob db3 main $snap } msg] $msg 97 -} {1 SQLITE_BUSY_SNAPSHOT} 97 +} {1 SQLITE_ERROR_SNAPSHOT} 98 98 99 99 finish_test 100 100
Added test/snapshot4.test.
1 +# 2018 August 28 2 +# 3 +# The author disclaims copyright to this source code. In place of 4 +# a legal notice, here is a blessing: 5 +# 6 +# May you do good and not evil. 7 +# May you find forgiveness for yourself and forgive others. 8 +# May you share freely, never taking more than you give. 9 +# 10 +#*********************************************************************** 11 +# This file implements regression tests for SQLite library. The focus 12 +# of this file is the sqlite3_snapshot_xxx() APIs. 13 +# 14 + 15 +set testdir [file dirname $argv0] 16 +source $testdir/tester.tcl 17 +ifcapable !snapshot {finish_test; return} 18 +set testprefix snapshot4 19 + 20 +# This test does not work with the inmemory_journal permutation. The reason 21 +# is that each connection opened as part of this permutation executes 22 +# "PRAGMA journal_mode=memory", which fails if the database is in wal mode 23 +# and there are one or more existing connections. 24 +if {[permutation]=="inmemory_journal"} { 25 + finish_test 26 + return 27 +} 28 + 29 +sqlite3 db2 test.db 30 + 31 +do_execsql_test 1.0 { 32 + PRAGMA cache_size = 10; 33 + CREATE TABLE t1(a, b); 34 + INSERT INTO t1 VALUES(1, randomblob(400)); 35 + PRAGMA journal_mode = wal; 36 + WITH s(i) AS ( 37 + SELECT 2 UNION ALL SELECT i+1 FROM s WHERE i<100 38 + ) 39 + INSERT INTO t1 SELECT i, randomblob(400) FROM s; 40 +} {wal} 41 + 42 +do_test 1.1 { 43 + execsql { 44 + BEGIN; 45 + SELECT count(*) FROM t1; 46 + } 47 +} {100} 48 + 49 +do_test 1.2 { 50 + db2 eval { 51 + SELECT count(*) FROM t1; 52 + CREATE TABLE t2(x); 53 + } 54 +} {100} 55 + 56 +do_test 1.3 { 57 + set ::snap [sqlite3_snapshot_get_blob db main] 58 + db2 eval { PRAGMA wal_checkpoint } 59 +} {0 54 52} 60 + 61 +do_test 1.4 { 62 + execsql { 63 + COMMIT; 64 + SELECT * FROM sqlite_master; 65 + BEGIN; 66 + } 67 + sqlite3_snapshot_open_blob db main $::snap 68 + execsql { 69 + SELECT count(*) FROM t1 70 + } 71 +} {100} 72 + 73 + 74 +finish_test 75 +
Changes to test/snapshot_fault.test.
43 43 INSERT INTO t1 VALUES(6, randomblob(500), randomblob(500)); 44 44 } 45 45 } -body { 46 46 db eval { PRAGMA wal_checkpoint } 47 47 } -test { 48 48 db2 eval BEGIN 49 49 if {[catch { sqlite3_snapshot_open db2 main $::snapshot } msg]} { 50 - if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} { 50 + if {$msg != "SQLITE_ERROR_SNAPSHOT" && $msg != "SQLITE_BUSY"} { 51 51 error "error is $msg" 52 52 } 53 53 } else { 54 54 set res [db2 eval { 55 55 SELECT a FROM t1; 56 56 PRAGMA integrity_check; 57 57 }] ................................................................................ 94 94 db_save 95 95 db close 96 96 db_restore_and_reopen 97 97 db eval { SELECT * FROM t1 } 98 98 99 99 db eval BEGIN 100 100 if {[catch { sqlite3_snapshot_open db main $::snapshot } msg]} { 101 - if {$msg != "SQLITE_BUSY_SNAPSHOT" && $msg != "SQLITE_BUSY"} { 101 + if {$msg != "SQLITE_ERROR_SNAPSHOT" && $msg != "SQLITE_BUSY"} { 102 102 error "error is $msg" 103 103 } 104 104 } else { 105 105 # This branch should actually never be taken. But it was useful in 106 106 # determining whether or not this test was actually working (by 107 107 # running a modified version of SQLite that allowed snapshots to be 108 108 # opened following a recovery).
Changes to test/snapshot_up.test.
71 71 72 72 do_execsql_test 1.6 { 73 73 SELECT * FROM t1 74 74 } {1 2 3 4 5 6 7 8 9 10 11 12} 75 75 76 76 do_test 1.7 { 77 77 list [catch { sqlite3_snapshot_open db main $::snap1 } msg] $msg 78 -} {1 SQLITE_BUSY_SNAPSHOT} 78 +} {1 SQLITE_ERROR_SNAPSHOT} 79 79 80 80 do_execsql_test 1.8 { 81 81 SELECT * FROM t1 82 82 } {1 2 3 4 5 6 7 8 9 10 11 12} 83 83 84 84 do_test 1.9 { 85 85 execsql { COMMIT ; BEGIN } 86 86 list [catch { sqlite3_snapshot_open db main $::snap1 } msg] $msg 87 -} {1 SQLITE_BUSY_SNAPSHOT} 87 +} {1 SQLITE_ERROR_SNAPSHOT} 88 88 89 89 do_test 1.10 { 90 90 execsql { COMMIT } 91 91 execsql { 92 92 PRAGMA wal_checkpoint; 93 93 DELETE FROM t1 WHERE a = 1; 94 94 } db2 ................................................................................ 109 109 do_test 1.12 { 110 110 sqlite3_snapshot_open db main $::snap4 111 111 execsql { SELECT * FROM t1 } 112 112 } {4 5 6 7 8 9 10 11 12 13 14 15} 113 113 114 114 do_test 1.13 { 115 115 list [catch { sqlite3_snapshot_open db main $::snap3 } msg] $msg 116 -} {1 SQLITE_BUSY_SNAPSHOT} 116 +} {1 SQLITE_ERROR_SNAPSHOT} 117 117 do_test 1.14 { 118 118 execsql { SELECT * FROM t1 } 119 119 } {4 5 6 7 8 9 10 11 12 13 14 15} 120 120 121 121 db close 122 122 db2 close 123 123 sqlite3 db test.db 124 124 do_execsql_test 1.15 { 125 125 BEGIN; 126 126 SELECT * FROM t1 127 127 } {7 8 9 10 11 12 13 14 15} 128 128 do_test 1.16 { 129 129 list [catch { sqlite3_snapshot_open db main $::snap4 } msg] $msg 130 -} {1 SQLITE_BUSY_SNAPSHOT} 130 +} {1 SQLITE_ERROR_SNAPSHOT} 131 131 do_execsql_test 1.17 { COMMIT } 132 132 133 133 sqlite3_snapshot_free $::snap1 134 134 sqlite3_snapshot_free $::snap2 135 135 sqlite3_snapshot_free $::snap3 136 136 sqlite3_snapshot_free $::snap4 137 137
Changes to test/view.test.
687 687 return SQLITE_OK 688 688 } 689 689 set log "" 690 690 db authorizer ::authLogDelete 691 691 db eval {DROP VIEW x1;} 692 692 set log 693 693 } {} 694 + 695 +set res [list {SQLITE_DELETE sqlite_stat1 {} main {} {}}] 696 +ifcapable stat4 { lappend res {SQLITE_DELETE sqlite_stat4 {} main {} {}} } 694 697 do_test view-25.2 { 695 698 set log "" 696 699 db eval {DROP TABLE t25;} 697 700 set log 698 -} {{SQLITE_DELETE sqlite_stat1 {} main {} {}}} 701 +} $res 699 702 700 703 finish_test
Changes to test/without_rowid3.test.
945 945 } 946 946 } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} 947 947 948 948 949 949 # Test the sqlite_rename_parent() function directly. 950 950 # 951 951 proc test_rename_parent {zCreate zOld zNew} { 952 - db eval {SELECT sqlite_rename_parent($zCreate, $zOld, $zNew)} 952 + db eval {SELECT sqlite_rename_table('main', $zCreate, $zOld, $zNew, 0)} 953 953 } 954 954 do_test without_rowid3-14.2.1.1 { 955 955 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 956 956 } {{CREATE TABLE t1(a REFERENCES "t3")}} 957 957 do_test without_rowid3-14.2.1.2 { 958 958 test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 959 959 } {{CREATE TABLE t1(a REFERENCES t2)}}
Changes to tool/mksqlite3c.tcl.
95 95 foreach hdr { 96 96 btree.h 97 97 btreeInt.h 98 98 fts3.h 99 99 fts3Int.h 100 100 fts3_hash.h 101 101 fts3_tokenizer.h 102 + geopoly.c 102 103 hash.h 103 104 hwtime.h 104 105 keywordhash.h 105 106 msvc.h 106 107 mutex.h 107 108 opcodes.h 108 109 os_common.h ................................................................................ 388 389 fts3_tokenizer1.c 389 390 fts3_tokenize_vtab.c 390 391 fts3_write.c 391 392 fts3_snippet.c 392 393 fts3_unicode.c 393 394 fts3_unicode2.c 394 395 396 + json1.c 395 397 rtree.c 396 398 icu.c 397 399 fts3_icu.c 398 400 sqlite3rbu.c 399 401 dbstat.c 400 402 dbpage.c 401 403 sqlite3session.c 402 - json1.c 403 404 fts5.c 404 405 stmt.c 405 406 } { 406 407 copy_file tsrc/$file 407 408 } 408 409 409 410 # Synthesize an alternative sqlite3_sourceid() implementation that