Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update the apple-osx branch so that it includes all of the latest trunk changes. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
b72f07b4a2cf62ac1b52d432f13057d5 |
User & Date: | drh 2012-04-19 20:43:54.884 |
Context
2012-05-05
| ||
01:03 | Merge the latest trunk changes into the apple-osx branch. (check-in: 2a99c0074a user: drh tags: apple-osx) | |
2012-04-19
| ||
20:43 | Update the apple-osx branch so that it includes all of the latest trunk changes. (check-in: b72f07b4a2 user: drh tags: apple-osx) | |
18:04 | Fix harmless compiler warnings on x64 MSVC, mostly in test code, but also in tclsqlite.c and in the FTS4 module. (check-in: 3281972eaa user: drh tags: trunk) | |
2012-04-03
| ||
19:43 | Cherrypick commit [1d5e744cc6] from the trunk in order to avoid leaving a file-descriptor open in test scripts capi3.test and capi3c.test. This is the version of SQLite that ships by default on the original Mountain Lion release. (check-in: 86b8481be7 user: dan tags: apple-osx, mountain-lion) | |
Changes
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for sqlite 3.7.12. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## |
︙ | ︙ | |||
739 740 741 742 743 744 745 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.7.12' PACKAGE_STRING='sqlite 3.7.12' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
1481 1482 1483 1484 1485 1486 1487 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.7.12 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.7.12:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.7.12 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.7.12, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
14028 14029 14030 14031 14032 14033 14034 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.7.12, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
14081 14082 14083 14084 14085 14086 14087 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 14094 14095 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ sqlite config.status 3.7.12 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to ext/fts3/fts3_icu.c.
︙ | ︙ | |||
106 107 108 109 110 111 112 | UChar32 c; int iInput = 0; int iOut = 0; *ppCursor = 0; | > > > | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | UChar32 c; int iInput = 0; int iOut = 0; *ppCursor = 0; if( zInput==0 ){ nInput = 0; zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ nChar * sizeof(UChar) + /* IcuCursor.aChar[] */ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ |
︙ | ︙ |
Changes to ext/fts3/fts3_term.c.
︙ | ︙ | |||
84 85 86 87 88 89 90 | *pzErr = sqlite3_mprintf( "wrong number of arguments to fts4term constructor" ); return SQLITE_ERROR; } zDb = argv[1]; | | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | *pzErr = sqlite3_mprintf( "wrong number of arguments to fts4term constructor" ); return SQLITE_ERROR; } zDb = argv[1]; nDb = (int)strlen(zDb); zFts3 = argv[3]; nFts3 = (int)strlen(zFts3); rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); if( rc!=SQLITE_OK ) return rc; nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2; p = (Fts3termTable *)sqlite3_malloc(nByte); if( !p ) return SQLITE_NOMEM; |
︙ | ︙ |
Changes to ext/fts3/fts3_test.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly. */ #include <tcl.h> #include <string.h> #include <assert.h> | | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** that the sqlite3_tokenizer_module.xLanguage() method is invoked correctly. */ #include <tcl.h> #include <string.h> #include <assert.h> #if defined(SQLITE_TEST) #if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) /* Required so that the "ifdef SQLITE_ENABLE_FTS3" below works */ #include "fts3Int.h" #define NM_MAX_TOKEN 12 typedef struct NearPhrase NearPhrase; |
︙ | ︙ | |||
385 386 387 388 389 390 391 | pCsr = (test_tokenizer_cursor *)sqlite3_malloc(sizeof(test_tokenizer_cursor)); if( pCsr==0 ){ rc = SQLITE_NOMEM; }else{ memset(pCsr, 0, sizeof(test_tokenizer_cursor)); pCsr->aInput = pInput; if( nBytes<0 ){ | | | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | pCsr = (test_tokenizer_cursor *)sqlite3_malloc(sizeof(test_tokenizer_cursor)); if( pCsr==0 ){ rc = SQLITE_NOMEM; }else{ memset(pCsr, 0, sizeof(test_tokenizer_cursor)); pCsr->aInput = pInput; if( nBytes<0 ){ pCsr->nInput = (int)strlen(pInput); }else{ pCsr->nInput = nBytes; } } *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; return rc; |
︙ | ︙ | |||
438 439 440 441 442 443 444 | if( p==pEnd ){ rc = SQLITE_DONE; }else{ /* Advance to the end of the token */ const char *pToken = p; int nToken; while( p<pEnd && testIsTokenChar(*p) ) p++; | | | | | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | if( p==pEnd ){ rc = SQLITE_DONE; }else{ /* Advance to the end of the token */ const char *pToken = p; int nToken; while( p<pEnd && testIsTokenChar(*p) ) p++; nToken = (int)(p-pToken); /* Copy the token into the buffer */ if( nToken>pCsr->nBuffer ){ sqlite3_free(pCsr->aBuffer); pCsr->aBuffer = sqlite3_malloc(nToken); } if( pCsr->aBuffer==0 ){ rc = SQLITE_NOMEM; }else{ int i; if( pCsr->iLangid & 0x00000001 ){ for(i=0; i<nToken; i++) pCsr->aBuffer[i] = pToken[i]; }else{ for(i=0; i<nToken; i++) pCsr->aBuffer[i] = testTolower(pToken[i]); } pCsr->iToken++; pCsr->iInput = (int)(p - pCsr->aInput); *ppToken = pCsr->aBuffer; *pnBytes = nToken; *piStartOffset = (int)(pToken - pCsr->aInput); *piEndOffset = (int)(p - pCsr->aInput); *piPosition = pCsr->iToken; } } return rc; } |
︙ | ︙ | |||
526 527 528 529 530 531 532 533 | "fts3_configure_incr_load", fts3_configure_incr_load_cmd, 0, 0 ); Tcl_CreateObjCommand( interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0 ); return TCL_OK; } #endif /* ifdef SQLITE_TEST */ | > | 527 528 529 530 531 532 533 534 535 | "fts3_configure_incr_load", fts3_configure_incr_load_cmd, 0, 0 ); Tcl_CreateObjCommand( interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0 ); return TCL_OK; } #endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */ #endif /* ifdef SQLITE_TEST */ |
Changes to ext/fts3/fts3_write.c.
︙ | ︙ | |||
3735 3736 3737 3738 3739 3740 3741 | } /* Advance to the next output block */ pLeaf->iBlock++; pLeaf->key.n = 0; pLeaf->block.n = 0; | < | 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 | } /* Advance to the next output block */ pLeaf->iBlock++; pLeaf->key.n = 0; pLeaf->block.n = 0; nSuffix = nTerm; nSpace = 1; nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; } blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
179 180 181 182 183 184 185 186 187 188 189 190 191 192 | int eCoordType; }; /* Possible values for eCoordType: */ #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: ** ** m = M/3 ** ** If an R*-tree "Reinsert" operation is required, the same number of | > > > > > > > > > > > > > | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | int eCoordType; }; /* Possible values for eCoordType: */ #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 /* ** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will ** only deal with integer coordinates. No floating point operations ** will be done. */ #ifdef SQLITE_RTREE_INT_ONLY typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ typedef int RtreeValue; /* Low accuracy coordinate */ #else typedef double RtreeDValue; /* High accuracy coordinate */ typedef float RtreeValue; /* Low accuracy coordinate */ #endif /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: ** ** m = M/3 ** ** If an R*-tree "Reinsert" operation is required, the same number of |
︙ | ︙ | |||
214 215 216 217 218 219 220 | int iCell; /* Index of current cell in pNode */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ }; union RtreeCoord { | | | | > > > > | | | | | > | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | int iCell; /* Index of current cell in pNode */ int iStrategy; /* Copy of idxNum search parameter */ int nConstraint; /* Number of entries in aConstraint */ RtreeConstraint *aConstraint; /* Search constraints. */ }; union RtreeCoord { RtreeValue f; int i; }; /* ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord ** formatted as a RtreeDValue (double or int64). This macro assumes that local ** variable pRtree points to the Rtree structure associated with the ** RtreeCoord. */ #ifdef SQLITE_RTREE_INT_ONLY # define DCOORD(coord) ((RtreeDValue)coord.i) #else # define DCOORD(coord) ( \ (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ ((double)coord.f) : \ ((double)coord.i) \ ) #endif /* ** A search constraint. */ struct RtreeConstraint { int iCoord; /* Index of constrained coordinate */ int op; /* Constraining operation */ RtreeDValue rValue; /* Constraint value. */ int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ }; /* Possible values for RtreeConstraint.op */ #define RTREE_EQ 0x41 #define RTREE_LE 0x42 #define RTREE_LT 0x43 |
︙ | ︙ | |||
284 285 286 287 288 289 290 | /* ** An instance of this structure must be supplied as a blob argument to ** the right-hand-side of an SQL MATCH operator used to constrain an ** r-tree query. */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ | | | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | /* ** An instance of this structure must be supplied as a blob argument to ** the right-hand-side of an SQL MATCH operator used to constrain an ** r-tree query. */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); void *pContext; int nParam; RtreeDValue aParam[1]; }; /* ** When a geometry callback is created (see sqlite3_rtree_geometry_callback), ** a single instance of the following structure is allocated. It is used ** as the context for the user-function created by by s_r_g_c(). The object ** is eventually deleted by the destructor mechanism provided by ** sqlite3_create_function_v2() (which is called by s_r_g_c() to create ** the geometry callback function). */ struct RtreeGeomCallback { int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); void *pContext; }; #ifndef MAX # define MAX(x,y) ((x) < (y) ? (y) : (x)) #endif #ifndef MIN |
︙ | ︙ | |||
865 866 867 868 869 870 871 | static int testRtreeGeom( Rtree *pRtree, /* R-Tree object */ RtreeConstraint *pConstraint, /* MATCH constraint to test */ RtreeCell *pCell, /* Cell to test */ int *pbRes /* OUT: Test result */ ){ int i; | | | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | static int testRtreeGeom( Rtree *pRtree, /* R-Tree object */ RtreeConstraint *pConstraint, /* MATCH constraint to test */ RtreeCell *pCell, /* Cell to test */ int *pbRes /* OUT: Test result */ ){ int i; RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; int nCoord = pRtree->nDim*2; assert( pConstraint->op==RTREE_MATCH ); assert( pConstraint->pGeom ); for(i=0; i<nCoord; i++){ aCoord[i] = DCOORD(pCell->aCoord[i]); |
︙ | ︙ | |||
895 896 897 898 899 900 901 | int ii; int bRes = 0; int rc = SQLITE_OK; nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; | | | | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | int ii; int bRes = 0; int rc = SQLITE_OK; nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; bRes==0 && ii<pCursor->nConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH ); switch( p->op ){ case RTREE_LE: case RTREE_LT: |
︙ | ︙ | |||
948 949 950 951 952 953 954 | RtreeCell cell; int ii; *pbEof = 0; nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; ii<pCursor->nConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; | | | 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 | RtreeCell cell; int ii; *pbEof = 0; nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; ii<pCursor->nConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); int res; assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH ); switch( p->op ){ case RTREE_LE: res = (coord<=p->rValue); break; case RTREE_LT: res = (coord<p->rValue); break; |
︙ | ︙ | |||
1146 1147 1148 1149 1150 1151 1152 1153 1154 | if( i==0 ){ i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); sqlite3_result_int64(ctx, iRowid); }else{ RtreeCoord c; nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); | > | > > | 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 | if( i==0 ){ i64 iRowid = nodeGetRowid(pRtree, pCsr->pNode, pCsr->iCell); sqlite3_result_int64(ctx, iRowid); }else{ RtreeCoord c; nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); }else #endif { assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } } return SQLITE_OK; } |
︙ | ︙ | |||
1195 1196 1197 1198 1199 1200 1201 | /* Check that value is actually a blob. */ if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<(int)sizeof(RtreeMatchArg) | | | | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 | /* Check that value is actually a blob. */ if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR; /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<(int)sizeof(RtreeMatchArg) || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 ){ return SQLITE_ERROR; } pGeom = (sqlite3_rtree_geometry *)sqlite3_malloc( sizeof(sqlite3_rtree_geometry) + nBlob ); if( !pGeom ) return SQLITE_NOMEM; memset(pGeom, 0, sizeof(sqlite3_rtree_geometry)); p = (RtreeMatchArg *)&pGeom[1]; memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) ){ sqlite3_free(pGeom); return SQLITE_ERROR; } pGeom->pContext = p->pContext; pGeom->nParam = p->nParam; |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 | ** an sqlite3_rtree_geometry_callback() SQL user function. */ rc = deserializeGeometry(argv[ii], p); if( rc!=SQLITE_OK ){ break; } }else{ p->rValue = sqlite3_value_double(argv[ii]); } } } } if( rc==SQLITE_OK ){ pCsr->pNode = 0; | > > > > | 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 | ** an sqlite3_rtree_geometry_callback() SQL user function. */ rc = deserializeGeometry(argv[ii], p); if( rc!=SQLITE_OK ){ break; } }else{ #ifdef SQLITE_RTREE_INT_ONLY p->rValue = sqlite3_value_int64(argv[ii]); #else p->rValue = sqlite3_value_double(argv[ii]); #endif } } } } if( rc==SQLITE_OK ){ pCsr->pNode = 0; |
︙ | ︙ | |||
1415 1416 1417 1418 1419 1420 1421 | pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1)); return rc; } /* ** Return the N-dimensional volumn of the cell stored in *p. */ | | | | | | | | 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1)); return rc; } /* ** Return the N-dimensional volumn of the cell stored in *p. */ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ RtreeDValue area = (RtreeDValue)1; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); } return area; } /* ** Return the margin length of cell p. The margin length is the sum ** of the objects size in each dimension. */ static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ RtreeDValue margin = (RtreeDValue)0; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); } return margin; } /* ** Store the union of cells p1 and p2 in p1. */ |
︙ | ︙ | |||
1477 1478 1479 1480 1481 1482 1483 | } return 1; } /* ** Return the amount cell p would grow by if it were unioned with pCell. */ | | | | | | | < | | | < | | 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 | } return 1; } /* ** Return the amount cell p would grow by if it were unioned with pCell. */ static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ RtreeDValue area; RtreeCell cell; memcpy(&cell, p, sizeof(RtreeCell)); area = cellArea(pRtree, &cell); cellUnion(pRtree, &cell, pCell); return (cellArea(pRtree, &cell)-area); } #if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, RtreeCell *aCell, int nCell, int iExclude ){ int ii; RtreeDValue overlap = 0.0; for(ii=0; ii<nCell; ii++){ #if VARIANT_RSTARTREE_CHOOSESUBTREE if( ii!=iExclude ) #else assert( iExclude==-1 ); UNUSED_PARAMETER(iExclude); #endif { int jj; RtreeDValue o = (RtreeDValue)1; for(jj=0; jj<(pRtree->nDim*2); jj+=2){ RtreeDValue x1, x2; x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); if( x2<x1 ){ o = 0.0; break; }else{ o = o * (x2-x1); } } overlap += o; } } return overlap; } #endif #if VARIANT_RSTARTREE_CHOOSESUBTREE static RtreeDValue cellOverlapEnlargement( Rtree *pRtree, RtreeCell *p, RtreeCell *pInsert, RtreeCell *aCell, int nCell, int iExclude ){ RtreeDValue before, after; before = cellOverlap(pRtree, p, aCell, nCell, iExclude); cellUnion(pRtree, p, pInsert); after = cellOverlap(pRtree, p, aCell, nCell, iExclude); return (after-before); } #endif /* ** This function implements the ChooseLeaf algorithm from Gutman[84]. ** ChooseSubTree in r*tree terminology. |
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | RtreeNode *pNode; rc = nodeAcquire(pRtree, 1, 0, &pNode); for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ int iCell; sqlite3_int64 iBest = 0; | | | | | | 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 | RtreeNode *pNode; rc = nodeAcquire(pRtree, 1, 0, &pNode); for(ii=0; rc==SQLITE_OK && ii<(pRtree->iDepth-iHeight); ii++){ int iCell; sqlite3_int64 iBest = 0; RtreeDValue fMinGrowth = 0.0; RtreeDValue fMinArea = 0.0; #if VARIANT_RSTARTREE_CHOOSESUBTREE RtreeDValue fMinOverlap = 0.0; RtreeDValue overlap; #endif int nCell = NCELL(pNode); RtreeCell cell; RtreeNode *pChild; RtreeCell *aCell = 0; |
︙ | ︙ | |||
1600 1601 1602 1603 1604 1605 1606 | /* Select the child node which will be enlarged the least if pCell ** is inserted into it. Resolve ties by choosing the entry with ** the smallest area. */ for(iCell=0; iCell<nCell; iCell++){ int bBest = 0; | | | | 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 | /* Select the child node which will be enlarged the least if pCell ** is inserted into it. Resolve ties by choosing the entry with ** the smallest area. */ for(iCell=0; iCell<nCell; iCell++){ int bBest = 0; RtreeDValue growth; RtreeDValue area; nodeGetCell(pRtree, pNode, iCell, &cell); growth = cellGrowth(pRtree, &cell, pCell); area = cellArea(pRtree, &cell); #if VARIANT_RSTARTREE_CHOOSESUBTREE if( ii==(pRtree->iDepth-1) ){ overlap = cellOverlapEnlargement(pRtree,&cell,pCell,aCell,nCell,iCell); |
︙ | ︙ | |||
1728 1729 1730 1731 1732 1733 1734 | int nCell, int *piLeftSeed, int *piRightSeed ){ int i; int iLeftSeed = 0; int iRightSeed = 1; | | | | | | | | | | 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 | int nCell, int *piLeftSeed, int *piRightSeed ){ int i; int iLeftSeed = 0; int iRightSeed = 1; RtreeDValue maxNormalInnerWidth = (RtreeDValue)0; /* Pick two "seed" cells from the array of cells. The algorithm used ** here is the LinearPickSeeds algorithm from Gutman[1984]. The ** indices of the two seed cells in the array are stored in local ** variables iLeftSeek and iRightSeed. */ for(i=0; i<pRtree->nDim; i++){ RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); RtreeDValue x3 = x1; RtreeDValue x4 = x2; int jj; int iCellLeft = 0; int iCellRight = 0; for(jj=1; jj<nCell; jj++){ RtreeDValue left = DCOORD(aCell[jj].aCoord[i*2]); RtreeDValue right = DCOORD(aCell[jj].aCoord[i*2+1]); if( left<x1 ) x1 = left; if( right>x4 ) x4 = right; if( left>x3 ){ x3 = left; iCellRight = jj; } if( right<x2 ){ x2 = right; iCellLeft = jj; } } if( x4!=x1 ){ RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); if( normalwidth>maxNormalInnerWidth ){ iLeftSeed = iCellLeft; iRightSeed = iCellRight; } } } |
︙ | ︙ | |||
1791 1792 1793 1794 1795 1796 1797 | RtreeCell *pLeftBox, RtreeCell *pRightBox, int *aiUsed ){ #define FABS(a) ((a)<0.0?-1.0*(a):(a)) int iSelect = -1; | | | | | | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 | RtreeCell *pLeftBox, RtreeCell *pRightBox, int *aiUsed ){ #define FABS(a) ((a)<0.0?-1.0*(a):(a)) int iSelect = -1; RtreeDValue fDiff; int ii; for(ii=0; ii<nCell; ii++){ if( aiUsed[ii]==0 ){ RtreeDValue left = cellGrowth(pRtree, pLeftBox, &aCell[ii]); RtreeDValue right = cellGrowth(pRtree, pLeftBox, &aCell[ii]); RtreeDValue diff = FABS(right-left); if( iSelect<0 || diff>fDiff ){ fDiff = diff; iSelect = ii; } } } aiUsed[iSelect] = 1; |
︙ | ︙ | |||
1824 1825 1826 1827 1828 1829 1830 | int *piRightSeed ){ int ii; int jj; int iLeftSeed = 0; int iRightSeed = 1; | | | | | | 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 | int *piRightSeed ){ int ii; int jj; int iLeftSeed = 0; int iRightSeed = 1; RtreeDValue fWaste = 0.0; for(ii=0; ii<nCell; ii++){ for(jj=ii+1; jj<nCell; jj++){ RtreeDValue right = cellArea(pRtree, &aCell[jj]); RtreeDValue growth = cellGrowth(pRtree, &aCell[ii], &aCell[jj]); RtreeDValue waste = growth - right; if( waste>fWaste ){ iLeftSeed = ii; iRightSeed = jj; fWaste = waste; } } |
︙ | ︙ | |||
1865 1866 1867 1868 1869 1870 1871 | ** ** The aSpare array is used as temporary working space by the ** sorting algorithm. */ static void SortByDistance( int *aIdx, int nIdx, | | | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 | ** ** The aSpare array is used as temporary working space by the ** sorting algorithm. */ static void SortByDistance( int *aIdx, int nIdx, RtreeDValue *aDistance, int *aSpare ){ if( nIdx>1 ){ int iLeft = 0; int iRight = 0; int nLeft = nIdx/2; |
︙ | ︙ | |||
1891 1892 1893 1894 1895 1896 1897 | if( iLeft==nLeft ){ aIdx[iLeft+iRight] = aRight[iRight]; iRight++; }else if( iRight==nRight ){ aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ | | | | | | 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 | if( iLeft==nLeft ){ aIdx[iLeft+iRight] = aRight[iRight]; iRight++; }else if( iRight==nRight ){ aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ RtreeDValue fLeft = aDistance[aLeft[iLeft]]; RtreeDValue fRight = aDistance[aRight[iRight]]; if( fLeft<fRight ){ aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ aIdx[iLeft+iRight] = aRight[iRight]; iRight++; } } } #if 0 /* Check that the sort worked */ { int jj; for(jj=1; jj<nIdx; jj++){ RtreeDValue left = aDistance[aIdx[jj-1]]; RtreeDValue right = aDistance[aIdx[jj]]; assert( left<=right ); } } #endif } } |
︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 | SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare); SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare); memcpy(aSpare, aLeft, sizeof(int)*nLeft); aLeft = aSpare; while( iLeft<nLeft || iRight<nRight ){ | | | | | | | | | | 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 | SortByDimension(pRtree, aLeft, nLeft, iDim, aCell, aSpare); SortByDimension(pRtree, aRight, nRight, iDim, aCell, aSpare); memcpy(aSpare, aLeft, sizeof(int)*nLeft); aLeft = aSpare; while( iLeft<nLeft || iRight<nRight ){ RtreeDValue xleft1 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2]); RtreeDValue xleft2 = DCOORD(aCell[aLeft[iLeft]].aCoord[iDim*2+1]); RtreeDValue xright1 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2]); RtreeDValue xright2 = DCOORD(aCell[aRight[iRight]].aCoord[iDim*2+1]); if( (iLeft!=nLeft) && ((iRight==nRight) || (xleft1<xright1) || (xleft1==xright1 && xleft2<xright2) )){ aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ aIdx[iLeft+iRight] = aRight[iRight]; iRight++; } } #if 0 /* Check that the sort worked */ { int jj; for(jj=1; jj<nIdx; jj++){ RtreeDValue xleft1 = aCell[aIdx[jj-1]].aCoord[iDim*2]; RtreeDValue xleft2 = aCell[aIdx[jj-1]].aCoord[iDim*2+1]; RtreeDValue xright1 = aCell[aIdx[jj]].aCoord[iDim*2]; RtreeDValue xright2 = aCell[aIdx[jj]].aCoord[iDim*2+1]; assert( xleft1<=xright1 && (xleft1<xright1 || xleft2<=xright2) ); } } #endif } } |
︙ | ︙ | |||
2003 2004 2005 2006 2007 2008 2009 | ){ int **aaSorted; int *aSpare; int ii; int iBestDim = 0; int iBestSplit = 0; | | | | | | | | 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 | ){ int **aaSorted; int *aSpare; int ii; int iBestDim = 0; int iBestSplit = 0; RtreeDValue fBestMargin = 0.0; int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int)); aaSorted = (int **)sqlite3_malloc(nByte); if( !aaSorted ){ return SQLITE_NOMEM; } aSpare = &((int *)&aaSorted[pRtree->nDim])[pRtree->nDim*nCell]; memset(aaSorted, 0, nByte); for(ii=0; ii<pRtree->nDim; ii++){ int jj; aaSorted[ii] = &((int *)&aaSorted[pRtree->nDim])[ii*nCell]; for(jj=0; jj<nCell; jj++){ aaSorted[ii][jj] = jj; } SortByDimension(pRtree, aaSorted[ii], nCell, ii, aCell, aSpare); } for(ii=0; ii<pRtree->nDim; ii++){ RtreeDValue margin = 0.0; RtreeDValue fBestOverlap = 0.0; RtreeDValue fBestArea = 0.0; int iBestLeft = 0; int nLeft; for( nLeft=RTREE_MINCELLS(pRtree); nLeft<=(nCell-RTREE_MINCELLS(pRtree)); nLeft++ ){ RtreeCell left; RtreeCell right; int kk; RtreeDValue overlap; RtreeDValue area; memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); for(kk=1; kk<(nCell-1); kk++){ if( kk<nLeft ){ cellUnion(pRtree, &left, &aCell[aaSorted[ii][kk]]); }else{ |
︙ | ︙ | |||
2122 2123 2124 2125 2126 2127 2128 | nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]); aiUsed[iLeftSeed] = 1; aiUsed[iRightSeed] = 1; for(i=nCell-2; i>0; i--){ RtreeCell *pNext; pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); | | | 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 | nodeInsertCell(pRtree, pRight, &aCell[iRightSeed]); aiUsed[iLeftSeed] = 1; aiUsed[iRightSeed] = 1; for(i=nCell-2; i>0; i--){ RtreeCell *pNext; pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); RtreeDValue diff = cellGrowth(pRtree, pBboxLeft, pNext) - cellGrowth(pRtree, pBboxRight, pNext) ; if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i) || (diff>0.0 && (RTREE_MINCELLS(pRtree)-NCELL(pLeft)!=i)) ){ nodeInsertCell(pRtree, pRight, pNext); |
︙ | ︙ | |||
2455 2456 2457 2458 2459 2460 2461 | RtreeNode *pNode, RtreeCell *pCell, int iHeight ){ int *aOrder; int *aSpare; RtreeCell *aCell; | | | > | > | | | | | | | | | | | | | | 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 | RtreeNode *pNode, RtreeCell *pCell, int iHeight ){ int *aOrder; int *aSpare; RtreeCell *aCell; RtreeDValue *aDistance; int nCell; RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS]; int iDim; int ii; int rc = SQLITE_OK; int n; memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS); nCell = NCELL(pNode)+1; n = (nCell+1)&(~1); /* Allocate the buffers used by this operation. The allocation is ** relinquished before this function returns. */ aCell = (RtreeCell *)sqlite3_malloc(n * ( sizeof(RtreeCell) + /* aCell array */ sizeof(int) + /* aOrder array */ sizeof(int) + /* aSpare array */ sizeof(RtreeDValue) /* aDistance array */ )); if( !aCell ){ return SQLITE_NOMEM; } aOrder = (int *)&aCell[n]; aSpare = (int *)&aOrder[n]; aDistance = (RtreeDValue *)&aSpare[n]; for(ii=0; ii<nCell; ii++){ if( ii==(nCell-1) ){ memcpy(&aCell[ii], pCell, sizeof(RtreeCell)); }else{ nodeGetCell(pRtree, pNode, ii, &aCell[ii]); } aOrder[ii] = ii; for(iDim=0; iDim<pRtree->nDim; iDim++){ aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); } } for(iDim=0; iDim<pRtree->nDim; iDim++){ aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); } for(ii=0; ii<nCell; ii++){ aDistance[ii] = 0.0; for(iDim=0; iDim<pRtree->nDim; iDim++){ RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - DCOORD(aCell[ii].aCoord[iDim*2])); aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); } } SortByDistance(aOrder, nCell, aDistance, aSpare); nodeZero(pRtree, pNode); |
︙ | ︙ | |||
2744 2745 2746 2747 2748 2749 2750 2751 2752 | ** conflict-handling mode specified by the user. */ if( nData>1 ){ int ii; /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ assert( nData==(pRtree->nDim*2 + 3) ); if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; ii<(pRtree->nDim*2); ii+=2){ | > | | | > > | 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 | ** conflict-handling mode specified by the user. */ if( nData>1 ){ int ii; /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ assert( nData==(pRtree->nDim*2 + 3) ); #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; ii<(pRtree->nDim*2); ii+=2){ cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]); cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ rc = SQLITE_CONSTRAINT; goto constraint; } } }else #endif { for(ii=0; ii<(pRtree->nDim*2); ii+=2){ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){ rc = SQLITE_CONSTRAINT; goto constraint; } |
︙ | ︙ | |||
3151 3152 3153 3154 3155 3156 3157 | RtreeCell cell; int jj; nodeGetCell(&tree, &node, ii, &cell); sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); nCell = (int)strlen(zCell); for(jj=0; jj<tree.nDim*2; jj++){ | > | > > > > > | 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 | RtreeCell cell; int jj; nodeGetCell(&tree, &node, ii, &cell); sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); nCell = (int)strlen(zCell); for(jj=0; jj<tree.nDim*2; jj++){ #ifndef SQLITE_RTREE_INT_ONLY sqlite3_snprintf(512-nCell,&zCell[nCell], " %f", (double)cell.aCoord[jj].f); #else sqlite3_snprintf(512-nCell,&zCell[nCell], " %d", cell.aCoord[jj].i); #endif nCell = (int)strlen(zCell); } if( zText ){ char *zTextNew = sqlite3_mprintf("%s {%s}", zText, zCell); sqlite3_free(zText); zText = zTextNew; |
︙ | ︙ | |||
3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 | int rc; rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); } if( rc==SQLITE_OK ){ void *c = (void *)RTREE_COORD_REAL32; rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); } if( rc==SQLITE_OK ){ void *c = (void *)RTREE_COORD_INT32; rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); } | > > > > | 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 | int rc; rc = sqlite3_create_function(db, "rtreenode", 2, utf8, 0, rtreenode, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "rtreedepth", 1, utf8, 0,rtreedepth, 0, 0); } if( rc==SQLITE_OK ){ #ifdef SQLITE_RTREE_INT_ONLY void *c = (void *)RTREE_COORD_INT32; #else void *c = (void *)RTREE_COORD_REAL32; #endif rc = sqlite3_create_module_v2(db, "rtree", &rtreeModule, c, 0); } if( rc==SQLITE_OK ){ void *c = (void *)RTREE_COORD_INT32; rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0); } |
︙ | ︙ | |||
3227 3228 3229 3230 3231 3232 3233 | ** table MATCH operators. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; int nBlob; | | > > > > | | 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 | ** table MATCH operators. */ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx); RtreeMatchArg *pBlob; int nBlob; nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue); pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob); if( !pBlob ){ sqlite3_result_error_nomem(ctx); }else{ int i; pBlob->magic = RTREE_GEOMETRY_MAGIC; pBlob->xGeom = pGeomCtx->xGeom; pBlob->pContext = pGeomCtx->pContext; pBlob->nParam = nArg; for(i=0; i<nArg; i++){ #ifdef SQLITE_RTREE_INT_ONLY pBlob->aParam[i] = sqlite3_value_int64(aArg[i]); #else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); #endif } sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); } } /* ** Register a new geometry function for use with the r-tree MATCH operator. */ int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), void *pContext ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ /* Allocate and populate the context object. */ pGeomCtx = (RtreeGeomCallback *)sqlite3_malloc(sizeof(RtreeGeomCallback)); if( !pGeomCtx ) return SQLITE_NOMEM; |
︙ | ︙ |
Changes to ext/rtree/rtree1.test.
︙ | ︙ | |||
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | catchsql " CREATE VIRTUAL TABLE t1 USING rtree($columns); " } $X catchsql { DROP TABLE t1 } } # Test that it is possible to open an existing database that contains # r-tree tables. # do_test rtree-1.4.1 { execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2); INSERT INTO t1 VALUES(1, 5.0, 10.0); INSERT INTO t1 VALUES(2, 15.0, 20.0); } } {} do_test rtree-1.4.2 { db close sqlite3 db test.db | > > > > > > > > > > > > | | | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | catchsql " CREATE VIRTUAL TABLE t1 USING rtree($columns); " } $X catchsql { DROP TABLE t1 } } # Like execsql except display output as integer where that can be # done without loss of information. # proc execsql_intout {sql} { set out {} foreach term [execsql $sql] { regsub {\.0$} $term {} term lappend out $term } return $out } # Test that it is possible to open an existing database that contains # r-tree tables. # do_test rtree-1.4.1 { execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2); INSERT INTO t1 VALUES(1, 5.0, 10.0); INSERT INTO t1 VALUES(2, 15.0, 20.0); } } {} do_test rtree-1.4.2 { db close sqlite3 db test.db execsql_intout { SELECT * FROM t1 ORDER BY ii } } {1 5 10 2 15 20} do_test rtree-1.4.3 { execsql { DROP TABLE t1 } } {} # Test that it is possible to create an r-tree table with ridiculous # column names. # do_test rtree-1.5.1 { execsql_intout { CREATE VIRTUAL TABLE t1 USING rtree("the key", "x dim.", "x2'dim"); INSERT INTO t1 VALUES(1, 2, 3); SELECT "the key", "x dim.", "x2'dim" FROM t1; } } {1 2 3} do_test rtree-1.5.1 { execsql { DROP TABLE t1 } } {} # Force the r-tree constructor to fail. # do_test rtree-1.6.1 { |
︙ | ︙ | |||
157 158 159 160 161 162 163 | CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2); SELECT * FROM t1; } } {} do_test rtree-2.1.2 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2); SELECT * FROM t1; } } {} do_test rtree-2.1.2 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } execsql_intout { SELECT * FROM t1 } } {1 1 3 2 4} do_test rtree-2.1.3 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } execsql { SELECT rowid FROM t1 ORDER BY rowid } } {1 2} do_test rtree-2.1.3 { execsql { INSERT INTO t1 VALUES(NULL, 1, 3, 2, 4) } execsql { SELECT ii FROM t1 ORDER BY ii } |
︙ | ︙ | |||
197 198 199 200 201 202 203 | do_test rtree-3.1.1 { execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2); SELECT * FROM t1; } } {} do_test rtree-3.1.2 { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | do_test rtree-3.1.1 { execsql { CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2, y1, y2); SELECT * FROM t1; } } {} do_test rtree-3.1.2 { execsql_intout { INSERT INTO t1 VALUES(5, 1, 3, 2, 4); SELECT * FROM t1; } } {5 1 3 2 4} do_test rtree-3.1.3 { execsql_intout { INSERT INTO t1 VALUES(6, 2, 6, 4, 8); SELECT * FROM t1; } } {5 1 3 2 4 6 2 6 4 8} # Test the constraint on the coordinates (c[i]<=c[i+1] where (i%2==0)): do_test rtree-3.2.1 { catchsql { INSERT INTO t1 VALUES(7, 2, 6, 4, 3) } } {1 {constraint failed}} do_test rtree-3.2.2 { catchsql { INSERT INTO t1 VALUES(8, 2, 6, 3, 3) } } {0 {}} #---------------------------------------------------------------------------- # Test cases rtree-5.* test DELETE operations. # do_test rtree-5.1.1 { execsql { CREATE VIRTUAL TABLE t2 USING rtree(ii, x1, x2) } } {} do_test rtree-5.1.2 { execsql_intout { INSERT INTO t2 VALUES(1, 10, 20); INSERT INTO t2 VALUES(2, 30, 40); INSERT INTO t2 VALUES(3, 50, 60); SELECT * FROM t2 ORDER BY ii; } } {1 10 20 2 30 40 3 50 60} do_test rtree-5.1.3 { execsql_intout { DELETE FROM t2 WHERE ii=2; SELECT * FROM t2 ORDER BY ii; } } {1 10 20 3 50 60} do_test rtree-5.1.4 { execsql_intout { DELETE FROM t2 WHERE ii=1; SELECT * FROM t2 ORDER BY ii; } } {3 50 60} do_test rtree-5.1.5 { execsql { DELETE FROM t2 WHERE ii=3; SELECT * FROM t2 ORDER BY ii; } } {} do_test rtree-5.1.6 { execsql { SELECT * FROM t2_rowid } } {} #---------------------------------------------------------------------------- # Test cases rtree-5.* test UPDATE operations. # do_test rtree-6.1.1 { execsql { CREATE VIRTUAL TABLE t3 USING rtree(ii, x1, x2, y1, y2) } } {} do_test rtree-6.1.2 { execsql_intout { INSERT INTO t3 VALUES(1, 2, 3, 4, 5); UPDATE t3 SET x2=5; SELECT * FROM t3; } } {1 2 5 4 5} do_test rtree-6.1.3 { execsql { UPDATE t3 SET ii = 2 } execsql_intout { SELECT * FROM t3 } } {2 2 5 4 5} #---------------------------------------------------------------------------- # Test cases rtree-7.* test rename operations. # do_test rtree-7.1.1 { execsql { CREATE VIRTUAL TABLE t4 USING rtree(ii, x1, x2, y1, y2, z1, z2); INSERT INTO t4 VALUES(1, 2, 3, 4, 5, 6, 7); } } {} do_test rtree-7.1.2 { execsql { ALTER TABLE t4 RENAME TO t5 } execsql_intout { SELECT * FROM t5 } } {1 2 3 4 5 6 7} do_test rtree-7.1.3 { db close sqlite3 db test.db execsql_intout { SELECT * FROM t5 } } {1 2 3 4 5 6 7} do_test rtree-7.1.4 { execsql { ALTER TABLE t5 RENAME TO 'raisara "one"'''} execsql_intout { SELECT * FROM "raisara ""one""'" } } {1 2 3 4 5 6 7} do_test rtree-7.1.5 { execsql_intout { SELECT * FROM 'raisara "one"''' } } {1 2 3 4 5 6 7} do_test rtree-7.1.6 { execsql { ALTER TABLE "raisara ""one""'" RENAME TO "abc 123" } execsql_intout { SELECT * FROM "abc 123" } } {1 2 3 4 5 6 7} do_test rtree-7.1.7 { db close sqlite3 db test.db execsql_intout { SELECT * FROM "abc 123" } } {1 2 3 4 5 6 7} # An error midway through a rename operation. do_test rtree-7.2.1 { execsql { CREATE TABLE t4_node(a); } catchsql { ALTER TABLE "abc 123" RENAME TO t4 } } {1 {SQL logic error or missing database}} do_test rtree-7.2.2 { execsql_intout { SELECT * FROM "abc 123" } } {1 2 3 4 5 6 7} do_test rtree-7.2.3 { execsql { DROP TABLE t4_node; CREATE TABLE t4_rowid(a); } catchsql { ALTER TABLE "abc 123" RENAME TO t4 } } {1 {SQL logic error or missing database}} do_test rtree-7.2.4 { db close sqlite3 db test.db execsql_intout { SELECT * FROM "abc 123" } } {1 2 3 4 5 6 7} do_test rtree-7.2.5 { execsql { DROP TABLE t4_rowid } execsql { ALTER TABLE "abc 123" RENAME TO t4 } execsql_intout { SELECT * FROM t4 } } {1 2 3 4 5 6 7} #---------------------------------------------------------------------------- # Test cases rtree-8.* # # Test that the function to determine if a leaf cell is part of the |
︙ | ︙ |
Changes to ext/rtree/rtree4.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | } set ::NROW 2500 if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } | > | | | | | | | | | | | | | | > > | > > > > > > > > > > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | } set ::NROW 2500 if {[info exists G(isquick)] && $G(isquick)} { set ::NROW 250 } ifcapable !rtree_int_only { # Return a floating point number between -X and X. # proc rand {X} { return [expr {int((rand()-0.5)*1024.0*$X)/512.0}] } # Return a positive floating point number less than or equal to X # proc randincr {X} { while 1 { set r [expr {int(rand()*$X*32.0)/32.0}] if {$r>0.0} {return $r} } } } else { # For rtree_int_only, return an number between -X and X. # proc rand {X} { return [expr {int((rand()-0.5)*2*$X)}] } # Return a positive integer less than or equal to X # proc randincr {X} { while 1 { set r [expr {int(rand()*$X)+1}] if {$r>0} {return $r} } } } # Scramble the $inlist into a random order. # proc scramble {inlist} { set y {} foreach x $inlist { lappend y [list [expr {rand()}] $x] } |
︙ | ︙ |
Changes to ext/rtree/rtree5.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | do_test rtree5-1.6 { execsql { SELECT x1==5.0 FROM t1 } } {1} do_test rtree5-1.7 { execsql { SELECT count(*) FROM t1 WHERE x1==5 } } {1} | > | | | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | do_test rtree5-1.6 { execsql { SELECT x1==5.0 FROM t1 } } {1} do_test rtree5-1.7 { execsql { SELECT count(*) FROM t1 WHERE x1==5 } } {1} ifcapable !rtree_int_only { do_test rtree5-1.8 { execsql { SELECT count(*) FROM t1 WHERE x1==5.2 } } {0} } do_test rtree5-1.9 { execsql { SELECT count(*) FROM t1 WHERE x1==5.0 } } {1} do_test rtree5-1.10 { execsql { SELECT (1<<31)-5, (1<<31)-1, -1*(1<<31), -1*(1<<31)+5 } } {2147483643 2147483647 -2147483648 -2147483643} |
︙ | ︙ |
Changes to ext/rtree/rtree6.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable {!rtree || rtree_int_only} { finish_test return } # Operator Byte Value # ---------------------- # = 0x41 ('A') |
︙ | ︙ |
Changes to ext/rtree/rtree7.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | } source $testdir/tester.tcl ifcapable !rtree||!vacuum { finish_test return } do_test rtree7-1.1 { execsql { PRAGMA page_size = 1024; CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2); INSERT INTO rt VALUES(1, 1, 2, 3, 4); } } {} do_test rtree7-1.2 { | > > > > > > > > > > > > | | | | | | | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | } source $testdir/tester.tcl ifcapable !rtree||!vacuum { finish_test return } # Like execsql except display output as integer where that can be # done without loss of information. # proc execsql_intout {sql} { set out {} foreach term [execsql $sql] { regsub {\.0$} $term {} term lappend out $term } return $out } do_test rtree7-1.1 { execsql { PRAGMA page_size = 1024; CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2); INSERT INTO rt VALUES(1, 1, 2, 3, 4); } } {} do_test rtree7-1.2 { execsql_intout { SELECT * FROM rt } } {1 1 2 3 4} do_test rtree7-1.3 { execsql_intout { PRAGMA page_size = 2048; VACUUM; SELECT * FROM rt; } } {1 1 2 3 4} do_test rtree7-1.4 { for {set i 2} {$i <= 51} {incr i} { execsql { INSERT INTO rt VALUES($i, 1, 2, 3, 4) } } execsql_intout { SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } } {51 102 153 204} do_test rtree7-1.5 { execsql_intout { PRAGMA page_size = 512; VACUUM; SELECT sum(x1), sum(x2), sum(y1), sum(y2) FROM rt } } {51 102 153 204} finish_test |
Changes to ext/rtree/rtree9.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } register_cube_geom db do_execsql_test rtree9-1.1 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2, z1, z2); INSERT INTO rt VALUES(1, 1, 2, 1, 2, 1, 2); } {} | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } ifcapable rtree_int_only { finish_test; return } register_cube_geom db do_execsql_test rtree9-1.1 { CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2, z1, z2); INSERT INTO rt VALUES(1, 1, 2, 1, 2, 1, 2); } {} |
︙ | ︙ |
Changes to ext/rtree/rtreeB.test.
︙ | ︙ | |||
14 15 16 17 18 19 20 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } | > > > > > > > > > > > > > | | | | | | | | | | | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | if {![info exists testdir]} { set testdir [file join [file dirname [info script]] .. .. test] } source $testdir/tester.tcl ifcapable !rtree { finish_test ; return } ifcapable rtree_int_only { do_test rtreeB-1.1-intonly { db eval { CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); SELECT rtreenode(2, data) FROM t1_node; } } {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}} } else { do_test rtreeB-1.1 { db eval { CREATE VIRTUAL TABLE t1 USING rtree(ii, x0, y0, x1, y1); INSERT INTO t1 VALUES(1073741824, 0.0, 0.0, 100.0, 100.0); INSERT INTO t1 VALUES(2147483646, 0.0, 0.0, 200.0, 200.0); INSERT INTO t1 VALUES(4294967296, 0.0, 0.0, 300.0, 300.0); INSERT INTO t1 VALUES(8589934592, 20.0, 20.0, 150.0, 150.0); INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400); SELECT rtreenode(2, data) FROM t1_node; } } {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}} } finish_test |
Changes to ext/rtree/sqlite3rtree.h.
︙ | ︙ | |||
27 28 29 30 31 32 33 | ** R-Tree geometry query as follows: ** ** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) */ int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, | > > > | > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ** R-Tree geometry query as follows: ** ** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...) */ int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, #ifdef SQLITE_RTREE_INT_ONLY int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), #else int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), #endif void *pContext ); /* ** A pointer to a structure of the following type is passed as the first ** argument to callbacks registered using rtree_geometry_callback(). |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 | if( pCheck->errMsg.mallocFailed ){ pCheck->mallocFailed = 1; } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } | > > > > > > > > > > > > > > > > > > > | > | | 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 | if( pCheck->errMsg.mallocFailed ){ pCheck->mallocFailed = 1; } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that ** corresponds to page iPg is already set. */ static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); } /* ** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. */ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); } /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. ** Return 1 if there are 2 ore more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ if( iPage==0 ) return 1; if( iPage>pCheck->nPage ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } setPageReferenced(pCheck, iPage); return 0; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Check that the entry in the pointer-map for page iChild maps to ** page iParent, pointer type ptrType. If not, append an error message ** to pCheck. |
︙ | ︙ | |||
7971 7972 7973 7974 7975 7976 7977 | sCheck.nErr = 0; sCheck.mallocFailed = 0; *pnErr = 0; if( sCheck.nPage==0 ){ sqlite3BtreeLeave(p); return 0; } | | > | < | < < | 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 | sCheck.nErr = 0; sCheck.mallocFailed = 0; *pnErr = 0; if( sCheck.nPage==0 ){ sqlite3BtreeLeave(p); return 0; } sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); |
︙ | ︙ | |||
8006 8007 8008 8009 8010 8011 8012 | checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); } /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM | | | | | | 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 | checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL); } /* Make sure every page in the file is referenced */ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain ** references to pointer-map pages. */ if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } #endif } /* Make sure this analysis did not leave any unref() pages. ** This is an internal consistency check; an integrity check ** of the integrity check. */ if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){ checkAppendMsg(&sCheck, 0, "Outstanding page count goes from %d to %d during this analysis", nRef, sqlite3PagerRefcount(pBt->pPager) ); } /* Clean up and report errors. */ sqlite3BtreeLeave(p); sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ sqlite3StrAccumReset(&sCheck.errMsg); *pnErr = sCheck.nErr+1; return 0; } *pnErr = sCheck.nErr; if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg); |
︙ | ︙ |
Changes to src/btreeInt.h.
︙ | ︙ | |||
627 628 629 630 631 632 633 634 635 636 637 638 | #define ISAUTOVACUUM 0 #endif /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ | > > > > > > | | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 | #define ISAUTOVACUUM 0 #endif /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. ** ** The aRef[] array is allocated so that there is 1 bit for each page in ** the database. As the integrity-check proceeds, for each page used in ** the database the corresponding bit is set. This allows integrity-check to ** detect pages that are used twice and orphaned pages (both of which ** indicate corruption). */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ StrAccum errMsg; /* Accumulate the error message text here */ }; |
︙ | ︙ |
Changes to src/callback.c.
︙ | ︙ | |||
218 219 220 221 222 223 224 225 226 227 | } /* During the search for the best function definition, this procedure ** is called to test how well the function passed as the first argument ** matches the request for a function with nArg arguments in a system ** that uses encoding enc. The value returned indicates how well the ** request is matched. A higher value indicates a better match. ** ** The returned value is always between 0 and 6, as follows: ** | > > > > > > > > | | < | < | | < | < | > > > > | > > > > | | > > | > > | > > > > > < < | > > | | < < | | | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | } /* During the search for the best function definition, this procedure ** is called to test how well the function passed as the first argument ** matches the request for a function with nArg arguments in a system ** that uses encoding enc. The value returned indicates how well the ** request is matched. A higher value indicates a better match. ** ** If nArg is -1 that means to only return a match (non-zero) if p->nArg ** is also -1. In other words, we are searching for a function that ** takes a variable number of arguments. ** ** If nArg is -2 that means that we are searching for any function ** regardless of the number of arguments it uses, so return a positive ** match score for any ** ** The returned value is always between 0 and 6, as follows: ** ** 0: Not a match. ** 1: UTF8/16 conversion required and function takes any number of arguments. ** 2: UTF16 byte order change required and function takes any number of args. ** 3: encoding matches and function takes any number of arguments ** 4: UTF8/16 conversion required - argument count matches exactly ** 5: UTF16 byte order conversion required - argument count matches exactly ** 6: Perfect match: encoding and argument count match exactly. ** ** If nArg==(-2) then any function with a non-null xStep or xFunc is ** a perfect match and any function with both xStep and xFunc NULL is ** a non-match. */ #define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ static int matchQuality( FuncDef *p, /* The function we are evaluating for match quality */ int nArg, /* Desired number of arguments. (-1)==any */ u8 enc /* Desired text encoding */ ){ int match; /* nArg of -2 is a special case */ if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH; /* Wrong number of arguments means "no match" */ if( p->nArg!=nArg && p->nArg>=0 ) return 0; /* Give a better score to a function with a specific number of arguments ** than to function that accepts any number of arguments. */ if( p->nArg==nArg ){ match = 4; }else{ match = 1; } /* Bonus points if the text encoding matches */ if( enc==p->iPrefEnc ){ match += 2; /* Exact encoding match */ }else if( (enc & p->iPrefEnc & 2)!=0 ){ match += 1; /* Both are UTF16, but with different byte orders */ } return match; } /* ** Search a FuncDefHash for a function with the given name. Return ** a pointer to the matching FuncDef if found, or 0 if there is no match. */ |
︙ | ︙ | |||
306 307 308 309 310 311 312 | ** Locate a user function given a name, a number of arguments and a flag ** indicating whether the function prefers UTF-16 over UTF-8. Return a ** pointer to the FuncDef structure that defines that function, or return ** NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a | | < < | | > | | | > | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | ** Locate a user function given a name, a number of arguments and a flag ** indicating whether the function prefers UTF-16 over UTF-8. Return a ** pointer to the FuncDef structure that defines that function, or return ** NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. ** ** If nArg is -2, then the first valid function found is returned. A ** function is valid if either xFunc or xStep is non-zero. The nArg==(-2) ** case is used to see if zName is a valid function name for some number ** of arguments. If nArg is -2, then createFlag must be 0. ** ** If createFlag is false, then a function with the required name and ** number of arguments may be returned even if the eTextRep flag does not ** match that requested. */ FuncDef *sqlite3FindFunction( sqlite3 *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ u8 createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *p; /* Iterator variable */ FuncDef *pBest = 0; /* Best match found so far */ int bestScore = 0; /* Score of best match */ int h; /* Hash value */ assert( nArg>=(-2) ); assert( nArg>=(-1) || createFlag==0 ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); /* First search for a match amongst the application-defined functions. */ p = functionSearch(&db->aFunc, h, zName, nName); while( p ){ |
︙ | ︙ | |||
377 378 379 380 381 382 383 | } } /* If the createFlag parameter is true and the search did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ | | | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | } } /* If the createFlag parameter is true and the search did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ if( createFlag && bestScore<FUNC_PERFECT_MATCH && (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ pBest->zName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; pBest->iPrefEnc = enc; memcpy(pBest->zName, zName, nName); pBest->zName[nName] = 0; sqlite3FuncDefInsert(&db->aFunc, pBest); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
3774 3775 3776 3777 3778 3779 3780 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } | | | 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 | if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } }else if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 2; } } if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; |
︙ | ︙ | |||
3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 | Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; if( sqlite3ExprCompare(pExprA, pExprB) ) return 1; } return 0; } /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. */ static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ int i; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 | Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; if( sqlite3ExprCompare(pExprA, pExprB) ) return 1; } return 0; } /* ** This is the expression callback for sqlite3FunctionUsesOtherSrc(). ** ** Determine if an expression references any table other than one of the ** tables in pWalker->u.pSrcList and abort if it does. */ static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ int i; SrcList *pSrc = pWalker->u.pSrcList; for(i=0; i<pSrc->nSrc; i++){ if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue; } return WRC_Abort; }else{ return WRC_Continue; } } /* ** Determine if any of the arguments to the pExpr Function references ** any SrcList other than pSrcList. Return true if they do. Return ** false if pExpr has no argument or has only constant arguments or ** only references tables named in pSrcList. */ static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; assert( pExpr->op==TK_AGG_FUNCTION ); memset(&w, 0, sizeof(w)); w.xExprCallback = exprUsesOtherSrc; w.u.pSrcList = pSrcList; if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1; return 0; } /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. */ static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ int i; |
︙ | ︙ | |||
3926 3927 3928 3929 3930 3931 3932 | break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } return WRC_Prune; } case TK_AGG_FUNCTION: { | | < < | 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 | break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } return WRC_Prune; } case TK_AGG_FUNCTION: { if( !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; i<pAggInfo->nFunc; i++, pItem++){ if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ break; |
︙ | ︙ | |||
3972 3973 3974 3975 3976 3977 3978 | return WRC_Prune; } } } return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ | | < < | < < < | < > | 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 | return WRC_Prune; } } } return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ UNUSED_PARAMETER(pWalker); UNUSED_PARAMETER(pSelect); return WRC_Continue; } /* ** Analyze the given expression looking for aggregate functions and ** for variables that need to be added to the pParse->aAgg[] array. ** Make additional entries to the pParse->aAgg[] array as necessary. ** ** This routine should only be called after the expression has been ** analyzed by sqlite3ResolveExprNames(). */ void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = analyzeAggregate; w.xSelectCallback = analyzeAggregatesInSelect; w.u.pNC = pNC; assert( pNC->pSrcList!=0 ); sqlite3WalkExpr(&w, pExpr); } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
1214 1215 1216 1217 1218 1219 1220 | } /* Test all CHECK constraints */ #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; | < | 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 | } /* Test all CHECK constraints */ #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
169 170 171 172 173 174 175 | ** Default permissions when creating a new file */ #ifndef SQLITE_DEFAULT_FILE_PERMISSIONS # define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 #endif /* | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | ** Default permissions when creating a new file */ #ifndef SQLITE_DEFAULT_FILE_PERMISSIONS # define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 #endif /* ** Default permissions when creating auto proxy dir */ #ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS # define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 #endif /* ** Maximum supported path-length. */ |
︙ | ︙ | |||
798 799 800 801 802 803 804 | if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName; } return 0; } /* ** Invoke open(). Do so multiple times, until it either succeeds or | | | > > > > > > | > > > | | 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName; } return 0; } /* ** Invoke open(). Do so multiple times, until it either succeeds or ** fails for some reason other than EINTR. ** ** If the file creation mode "m" is 0 then set it to the default for ** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally ** 0644) as modified by the system umask. If m is not 0, then ** make the file creation mode be exactly m ignoring the umask. ** ** The m parameter will be non-zero only when creating -wal, -journal, ** and -shm files. We want those files to have *exactly* the same ** permissions as their original database, unadulterated by the umask. ** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a ** transaction crashes and leaves behind hot journals, then any ** process that is able to write to the database will also be able to ** recover the hot journals. */ static int robust_open(const char *z, int f, mode_t m){ int fd; mode_t m2; mode_t origM = 0; if( m==0 ){ m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; }else{ m2 = m; origM = osUmask(0); } do{ #if defined(O_CLOEXEC) fd = osOpen(z,f|O_CLOEXEC,m2); #else fd = osOpen(z,f,m2); #endif }while( fd<0 && errno==EINTR ); if( m ){ osUmask(origM); } #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); #endif return fd; } /* ** Helper functions to obtain and relinquish the global mutex. The ** global mutex is used to protect the unixInodeInfo and ** vxworksFileId objects used by this file, all of which may be ** shared by multiple threads. |
︙ | ︙ | |||
3739 3740 3741 3742 3743 3744 3745 | sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); if( ii>0 ){ zDirname[ii] = '\0'; fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); if( fd>=0 ){ | < < < | 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 | sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--); if( ii>0 ){ zDirname[ii] = '\0'; fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); if( fd>=0 ){ OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); } } *pFd = fd; return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname)); } |
︙ | ︙ | |||
3832 3833 3834 3835 3836 3837 3838 | SimulateIOError( return SQLITE_IOERR_TRUNCATE ); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the ** actual file size after the operation may be larger than the requested ** size). */ | | | 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 | SimulateIOError( return SQLITE_IOERR_TRUNCATE ); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the ** actual file size after the operation may be larger than the requested ** size). */ if( pFile->szChunk>0 ){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } rc = robust_ftruncate(pFile->h, (off_t)nByte); if( rc ){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); |
︙ | ︙ | |||
6182 6183 6184 6185 6186 6187 6188 | } #if SQLITE_ENABLE_LOCKING_STYLE else{ p->openFlags = openFlags; } #endif | < < < < | 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 | } #if SQLITE_ENABLE_LOCKING_STYLE else{ p->openFlags = openFlags; } #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ ((unixFile*)pFile)->lastErrno = errno; robust_close(p, fd, __LINE__); |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
529 530 531 532 533 534 535 | testcase( pExpr->op==TK_CONST_FUNC ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ | | | 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | testcase( pExpr->op==TK_CONST_FUNC ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; |
︙ | ︙ |
Changes to src/rowset.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | ** The number of rowset entries per allocation chunk. */ #define ROWSET_ENTRY_PER_CHUNK \ ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) /* ** Each entry in a RowSet is an instance of the following object. */ struct RowSetEntry { i64 v; /* ROWID value for this entry */ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ }; | > > > > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | ** The number of rowset entries per allocation chunk. */ #define ROWSET_ENTRY_PER_CHUNK \ ((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry)) /* ** Each entry in a RowSet is an instance of the following object. ** ** This same object is reused to store a linked list of trees of RowSetEntry ** objects. In that alternative use, pRight points to the next entry ** in the list, pLeft points to the tree, and v is unused. The ** RowSet.pForest value points to the head of this forest list. */ struct RowSetEntry { i64 v; /* ROWID value for this entry */ struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */ struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */ }; |
︙ | ︙ | |||
101 102 103 104 105 106 107 | */ struct RowSet { struct RowSetChunk *pChunk; /* List of all chunk allocations */ sqlite3 *db; /* The database connection */ struct RowSetEntry *pEntry; /* List of entries using pRight */ struct RowSetEntry *pLast; /* Last entry on the pEntry list */ struct RowSetEntry *pFresh; /* Source of new entry objects */ | | | > > > > > > | | | > > | > > > > > > > > > > > > > > > > > > > > > > > < < < < < < | < < < > | | | | | | < | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | */ struct RowSet { struct RowSetChunk *pChunk; /* List of all chunk allocations */ sqlite3 *db; /* The database connection */ struct RowSetEntry *pEntry; /* List of entries using pRight */ struct RowSetEntry *pLast; /* Last entry on the pEntry list */ struct RowSetEntry *pFresh; /* Source of new entry objects */ struct RowSetEntry *pForest; /* List of binary trees of entries */ u16 nFresh; /* Number of objects on pFresh */ u8 rsFlags; /* Various flags */ u8 iBatch; /* Current insert batch */ }; /* ** Allowed values for RowSet.rsFlags */ #define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ #define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ /* ** Turn bulk memory into a RowSet object. N bytes of memory ** are available at pSpace. The db pointer is used as a memory context ** for any subsequent allocations that need to occur. ** Return a pointer to the new RowSet object. ** ** It must be the case that N is sufficient to make a Rowset. If not ** an assertion fault occurs. ** ** If N is larger than the minimum, use the surplus as an initial ** allocation of entries available to be filled. */ RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){ RowSet *p; assert( N >= ROUND8(sizeof(*p)) ); p = pSpace; p->pChunk = 0; p->db = db; p->pEntry = 0; p->pLast = 0; p->pForest = 0; p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); p->rsFlags = ROWSET_SORTED; p->iBatch = 0; return p; } /* ** Deallocate all chunks from a RowSet. This frees all memory that ** the RowSet has allocated over its lifetime. This routine is ** the destructor for the RowSet. */ void sqlite3RowSetClear(RowSet *p){ struct RowSetChunk *pChunk, *pNextChunk; for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){ pNextChunk = pChunk->pNextChunk; sqlite3DbFree(p->db, pChunk); } p->pChunk = 0; p->nFresh = 0; p->pEntry = 0; p->pLast = 0; p->pForest = 0; p->rsFlags = ROWSET_SORTED; } /* ** Allocate a new RowSetEntry object that is associated with the ** given RowSet. Return a pointer to the new and completely uninitialized ** objected. ** ** In an OOM situation, the RowSet.db->mallocFailed flag is set and this ** routine returns NULL. */ static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ assert( p!=0 ); if( p->nFresh==0 ){ struct RowSetChunk *pNew; pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); if( pNew==0 ){ return 0; } pNew->pNextChunk = p->pChunk; p->pChunk = pNew; p->pFresh = pNew->aEntry; p->nFresh = ROWSET_ENTRY_PER_CHUNK; } p->nFresh--; return p->pFresh++; } /* ** Insert a new value into a RowSet. ** ** The mallocFailed flag of the database connection is set if a ** memory allocation fails. */ void sqlite3RowSetInsert(RowSet *p, i64 rowid){ struct RowSetEntry *pEntry; /* The new entry */ struct RowSetEntry *pLast; /* The last prior entry */ /* This routine is never called after sqlite3RowSetNext() */ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); pEntry = rowSetEntryAlloc(p); if( pEntry==0 ) return; pEntry->v = rowid; pEntry->pRight = 0; pLast = p->pLast; if( pLast ){ if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ p->rsFlags &= ~ROWSET_SORTED; } pLast->pRight = pEntry; }else{ p->pEntry = pEntry; } p->pLast = pEntry; } /* ** Merge two lists of RowSetEntry objects. Remove duplicates. ** ** The input lists are connected via pRight pointers and are ** assumed to each already be in sorted order. */ static struct RowSetEntry *rowSetEntryMerge( struct RowSetEntry *pA, /* First sorted list to be merged */ struct RowSetEntry *pB /* Second sorted list to be merged */ ){ struct RowSetEntry head; struct RowSetEntry *pTail; pTail = &head; |
︙ | ︙ | |||
232 233 234 235 236 237 238 | assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); pTail->pRight = pB; } return head.pRight; } /* | | > | | < < | < | | | | > | | | < < | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | assert( pB==0 || pB->pRight==0 || pB->v<=pB->pRight->v ); pTail->pRight = pB; } return head.pRight; } /* ** Sort all elements on the list of RowSetEntry objects into order of ** increasing v. */ static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ unsigned int i; struct RowSetEntry *pNext, *aBucket[40]; memset(aBucket, 0, sizeof(aBucket)); while( pIn ){ pNext = pIn->pRight; pIn->pRight = 0; for(i=0; aBucket[i]; i++){ pIn = rowSetEntryMerge(aBucket[i], pIn); aBucket[i] = 0; } aBucket[i] = pIn; pIn = pNext; } pIn = 0; for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){ pIn = rowSetEntryMerge(pIn, aBucket[i]); } return pIn; } /* ** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects. ** Convert this tree into a linked list connected by the pRight pointers ** and return pointers to the first and last elements of the new list. |
︙ | ︙ | |||
351 352 353 354 355 356 357 | p->pLeft = pLeft; p->pRight = rowSetNDeepTree(&pList, iDepth); } return p; } /* | | | | > | > > | > > > > > > > > > > > | | | < | | > > > > > > > | > > > > > > | > > > > > > | > > > > > > > > > > > > > > > > > > | > > > | > > > > > > > | > | | | | | | | > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | p->pLeft = pLeft; p->pRight = rowSetNDeepTree(&pList, iDepth); } return p; } /* ** Take all the entries on p->pEntry and on the trees in p->pForest and ** sort them all together into one big ordered list on p->pEntry. ** ** This routine should only be called once in the life of a RowSet. */ static void rowSetToList(RowSet *p){ /* This routine is called only once */ assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); if( (p->rsFlags & ROWSET_SORTED)==0 ){ p->pEntry = rowSetEntrySort(p->pEntry); } /* While this module could theoretically support it, sqlite3RowSetNext() ** is never called after sqlite3RowSetText() for the same RowSet. So ** there is never a forest to deal with. Should this change, simply ** remove the assert() and the #if 0. */ assert( p->pForest==0 ); #if 0 while( p->pForest ){ struct RowSetEntry *pTree = p->pForest->pLeft; if( pTree ){ struct RowSetEntry *pHead, *pTail; rowSetTreeToList(pTree, &pHead, &pTail); p->pEntry = rowSetEntryMerge(p->pEntry, pHead); } p->pForest = p->pForest->pRight; } #endif p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ } /* ** Extract the smallest element from the RowSet. ** Write the element into *pRowid. Return 1 on success. Return ** 0 if the RowSet is already empty. ** ** After this routine has been called, the sqlite3RowSetInsert() ** routine may not be called again. */ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ assert( p!=0 ); /* Merge the forest into a single sorted list on first call */ if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); /* Return the next entry on the list */ if( p->pEntry ){ *pRowid = p->pEntry->v; p->pEntry = p->pEntry->pRight; if( p->pEntry==0 ){ sqlite3RowSetClear(p); } return 1; }else{ return 0; } } /* ** Check to see if element iRowid was inserted into the the rowset as ** part of any insert batch prior to iBatch. Return 1 or 0. ** ** If this is the first test of a new batch and if there exist entires ** on pRowSet->pEntry, then sort those entires into the forest at ** pRowSet->pForest so that they can be tested. */ int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ struct RowSetEntry *p, *pTree; /* This routine is never called after sqlite3RowSetNext() */ assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); /* Sort entries into the forest on the first test of a new batch */ if( iBatch!=pRowSet->iBatch ){ p = pRowSet->pEntry; if( p ){ struct RowSetEntry **ppPrevTree = &pRowSet->pForest; if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ p = rowSetEntrySort(p); } for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ ppPrevTree = &pTree->pRight; if( pTree->pLeft==0 ){ pTree->pLeft = rowSetListToTree(p); break; }else{ struct RowSetEntry *pAux, *pTail; rowSetTreeToList(pTree->pLeft, &pAux, &pTail); pTree->pLeft = 0; p = rowSetEntryMerge(pAux, p); } } if( pTree==0 ){ *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); if( pTree ){ pTree->v = 0; pTree->pRight = 0; pTree->pLeft = rowSetListToTree(p); } } pRowSet->pEntry = 0; pRowSet->pLast = 0; pRowSet->rsFlags |= ROWSET_SORTED; } pRowSet->iBatch = iBatch; } /* Test to see if the iRowid value appears anywhere in the forest. ** Return 1 if it does and 0 if not. */ for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ p = pTree->pLeft; while( p ){ if( p->v<iRowid ){ p = p->pRight; }else if( p->v>iRowid ){ p = p->pLeft; }else{ return 1; } } } return 0; } |
Changes to src/select.c.
︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 | int cnt; /* Index added to make the name unique */ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ Expr *p; /* Expression for a single result column */ char *zName; /* Column name */ int nName; /* Size of name in zName[] */ | > | | | > > > > > > > | 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 | int cnt; /* Index added to make the name unique */ Column *aCol, *pCol; /* For looping over result columns */ int nCol; /* Number of columns in the result set */ Expr *p; /* Expression for a single result column */ char *zName; /* Column name */ int nName; /* Size of name in zName[] */ if( pEList ){ nCol = pEList->nExpr; aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); testcase( aCol==0 ); }else{ nCol = 0; aCol = 0; } *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ |
︙ | ︙ | |||
2839 2840 2841 2842 2843 2844 2845 | } } /***** If we reach this point, flattening is permitted. *****/ /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; | | > | 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 | } } /***** If we reach this point, flattening is permitted. *****/ /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; /* If the sub-query is a compound SELECT statement, then (by restrictions ** 17 and 18 above) it must be a UNION ALL and the parent query must ** be of the form: ** ** SELECT <expr-list> FROM (<sub-query>) <where-clause> |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
417 418 419 420 421 422 423 424 425 426 427 428 429 430 | */ struct callback_data { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int statsOn; /* True to display memory stats before each finalize */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ char *zDestTable; /* Name of destination table when MODE_Insert */ char separator[20]; /* Separator character for MODE_List */ int colWidth[100]; /* Requested width of each column when in column mode*/ | > | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | */ struct callback_data { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int statsOn; /* True to display memory stats before each finalize */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ char *zDestTable; /* Name of destination table when MODE_Insert */ char separator[20]; /* Separator character for MODE_List */ int colWidth[100]; /* Requested width of each column when in column mode*/ |
︙ | ︙ | |||
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); /* Always quote the table name, even if it appears to be pure ascii, ** in case it is a keyword. Ex: INSERT INTO "table" ... */ zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); zSelect = appendText(zSelect, "quote(", 0); zSelect = appendText(zSelect, zText, '"'); | > | 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 | zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); /* Always quote the table name, even if it appears to be pure ascii, ** in case it is a keyword. Ex: INSERT INTO "table" ... */ zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); free(zTmp); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); zSelect = appendText(zSelect, "quote(", 0); zSelect = appendText(zSelect, zText, '"'); |
︙ | ︙ | |||
1333 1334 1335 1336 1337 1338 1339 | zSelect = appendText(zSelect, zTable, '"'); rc = run_table_dump_query(p, zSelect, zPrepStmt); if( rc==SQLITE_CORRUPT ){ zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); run_table_dump_query(p, zSelect, 0); } | | | 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 | zSelect = appendText(zSelect, zTable, '"'); rc = run_table_dump_query(p, zSelect, zPrepStmt); if( rc==SQLITE_CORRUPT ){ zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); run_table_dump_query(p, zSelect, 0); } free(zSelect); } return 0; } /* ** Run zQuery. Use dump_callback() as the callback routine so that ** the contents of the query are output as SQL statements. |
︙ | ︙ | |||
1363 1364 1365 1366 1367 1368 1369 | if( zErr ){ fprintf(p->out, "/****** %s ******/\n", zErr); sqlite3_free(zErr); zErr = 0; } zQ2 = malloc( len+100 ); if( zQ2==0 ) return rc; | | | 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 | if( zErr ){ fprintf(p->out, "/****** %s ******/\n", zErr); sqlite3_free(zErr); zErr = 0; } zQ2 = malloc( len+100 ); if( zQ2==0 ) return rc; sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery); rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); if( rc ){ fprintf(p->out, "/****** ERROR: %s ******/\n", zErr); }else{ rc = SQLITE_CORRUPT; } sqlite3_free(zErr); |
︙ | ︙ | |||
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | ".separator STRING Change separator used by output mode and .import\n" ".show Show the current values for various settings\n" ".stats ON|OFF Turn stats on or off\n" ".tables ?TABLE? List names of tables\n" " If TABLE specified, only list tables matching\n" " LIKE pattern TABLE.\n" ".timeout MS Try opening locked tables for MS milliseconds\n" ".vfsname ?AUX? Print the name of the VFS stack\n" ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" ; static char zTimerHelp[] = ".timer ON|OFF Turn the CPU timer measurement on or off\n" ; | > | 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 | ".separator STRING Change separator used by output mode and .import\n" ".show Show the current values for various settings\n" ".stats ON|OFF Turn stats on or off\n" ".tables ?TABLE? List names of tables\n" " If TABLE specified, only list tables matching\n" " LIKE pattern TABLE.\n" ".timeout MS Try opening locked tables for MS milliseconds\n" ".trace FILE|off Output each SQL statement as it is run\n" ".vfsname ?AUX? Print the name of the VFS stack\n" ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" ; static char zTimerHelp[] = ".timer ON|OFF Turn the CPU timer measurement on or off\n" ; |
︙ | ︙ | |||
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 | if( strcmp(zArg,"on")==0 ){ val = 1; }else if( strcmp(zArg,"yes")==0 ){ val = 1; } return val; } /* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | if( strcmp(zArg,"on")==0 ){ val = 1; }else if( strcmp(zArg,"yes")==0 ){ val = 1; } return val; } /* ** Close an output file, assuming it is not stderr or stdout */ static void output_file_close(FILE *f){ if( f && f!=stdout && f!=stderr ) fclose(f); } /* ** Try to open an output file. The names "stdout" and "stderr" are ** recognized and do the right thing. NULL is returned if the output ** filename is "off". */ static FILE *output_file_open(const char *zFile){ FILE *f; if( strcmp(zFile,"stdout")==0 ){ f = stdout; }else if( strcmp(zFile, "stderr")==0 ){ f = stderr; }else if( strcmp(zFile, "off")==0 ){ f = 0; }else{ f = fopen(zFile, "wb"); if( f==0 ){ fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); } } return f; } /* ** A routine for handling output from sqlite3_trace(). */ static void sql_trace_callback(void *pArg, const char *z){ FILE *f = (FILE*)pArg; if( f ) fprintf(f, "%s\n", z); } /* ** A no-op routine that runs with the ".breakpoint" doc-command. This is ** a useful spot to set a debugger breakpoint. */ static void test_breakpoint(void){ static int nCall = 0; nCall++; } /* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ |
︙ | ︙ | |||
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 | } sqlite3_close(pDest); }else if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){ bail_on_error = booleanValue(azArg[1]); }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 1; | > > > > > > > | 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 | } sqlite3_close(pDest); }else if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){ bail_on_error = booleanValue(azArg[1]); }else /* The undocumented ".breakpoint" command causes a call to the no-op ** routine named test_breakpoint(). */ if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){ test_breakpoint(); }else if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 1; |
︙ | ︙ | |||
1928 1929 1930 1931 1932 1933 1934 | rc = 1; } }else #endif if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){ const char *zFile = azArg[1]; | < | | < < < < < < < < < < < < < | 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 | rc = 1; } }else #endif if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){ const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile); }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){ int n2 = strlen30(azArg[1]); if( (n2==4 && strncmp(azArg[1],"line",n2)==0) || (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){ |
︙ | ︙ | |||
1996 1997 1998 1999 2000 2001 2002 | if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ | < | | | | | < < | < | | > | > | | 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 | if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->outfile[0]=='|' ){ pclose(p->out); }else{ output_file_close(p->out); } p->outfile[0] = 0; if( azArg[1][0]=='|' ){ p->out = popen(&azArg[1][1], "w"); if( p->out==0 ){ fprintf(stderr,"Error: cannot open pipe \"%s\"\n", &azArg[1][1]); p->out = stdout; rc = 1; }else{ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } }else{ p->out = output_file_open(azArg[1]); if( p->out==0 ){ if( strcmp(azArg[1],"off")!=0 ){ fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]); } p->out = stdout; rc = 1; } else { sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); } } }else if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ if( nArg >= 2) { strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); |
︙ | ︙ | |||
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 | if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){ enableTimer = booleanValue(azArg[1]); }else if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ printf("SQLite %s %s\n" /*extra-version-info*/, sqlite3_libversion(), sqlite3_sourceid()); }else if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ const char *zDbName = nArg==2 ? azArg[1] : "main"; | > > > > > > > > > > > > | 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 | if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg==2 ){ enableTimer = booleanValue(azArg[1]); }else if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){ output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); #ifndef SQLITE_OMIT_TRACE if( p->traceOut==0 ){ sqlite3_trace(p->db, 0, 0); }else{ sqlite3_trace(p->db, sql_trace_callback, p->traceOut); } #endif }else if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ printf("SQLite %s %s\n" /*extra-version-info*/, sqlite3_libversion(), sqlite3_sourceid()); }else if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ const char *zDbName = nArg==2 ? azArg[1] : "main"; |
︙ | ︙ | |||
2603 2604 2605 2606 2607 2608 2609 | } free(zLine); return errCnt; } /* ** Return a pathname which is the user's home directory. A | | < < | > | | 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 | } free(zLine); return errCnt; } /* ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ static char *home_dir = NULL; if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { home_dir = pwent->pw_dir; } #endif #if defined(_WIN32_WCE) /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() */ home_dir = "/"; #else #if defined(_WIN32) || defined(WIN32) || defined(__OS2__) if (!home_dir) { home_dir = getenv("USERPROFILE"); } #endif |
︙ | ︙ | |||
2677 2678 2679 2680 2681 2682 2683 | struct callback_data *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ char *home_dir = NULL; const char *sqliterc = sqliterc_override; char *zBuf = 0; FILE *in = NULL; | < < < < < < < | < | | | 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 | struct callback_data *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ char *home_dir = NULL; const char *sqliterc = sqliterc_override; char *zBuf = 0; FILE *in = NULL; int rc = 0; if (sqliterc == NULL) { home_dir = find_home_dir(); if( home_dir==0 ){ #if !defined(__RTP__) && !defined(_WRS_KERNEL) fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); #endif return 1; } zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); sqliterc = zBuf; } in = fopen(sqliterc,"rb"); if( in ){ if( stdin_is_interactive ){ fprintf(stderr,"-- Loading resources from %s\n",sqliterc); } rc = process_input(p,in); fclose(in); } sqlite3_free(zBuf); return rc; } /* ** Show available command line options */ static const char zOptions[] = |
︙ | ︙ | |||
3047 3048 3049 3050 3051 3052 3053 | #endif rc = process_input(&data, 0); if( zHistory ){ stifle_history(100); write_history(zHistory); free(zHistory); } | < | 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 | #endif rc = process_input(&data, 0); if( zHistory ){ stifle_history(100); write_history(zHistory); free(zHistory); } }else{ rc = process_input(&data, stdin); } } set_table_name(&data, 0); if( data.db ){ sqlite3_close(data.db); } return rc; } |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
1543 1544 1545 1546 1547 1548 1549 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] | | | 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2017 2018 2019 2020 2021 2022 2023 | SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; /* True if aggregates are seen */ u8 isCheck; /* True if resolving names in a CHECK constraint */ | < | 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 | SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; /* True if aggregates are seen */ u8 isCheck; /* True if resolving names in a CHECK constraint */ AggInfo *pAggInfo; /* Information about aggregates at this level */ NameContext *pNext; /* Next outer name context. NULL for outermost */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. |
︙ | ︙ | |||
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 | struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ Parse *pParse; /* Parser context. */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); | > | 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 | struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ Parse *pParse; /* Parser context. */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ SrcList *pSrcList; /* FROM clause */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); |
︙ | ︙ | |||
2851 2852 2853 2854 2855 2856 2857 | void sqlite3HaltConstraint(Parse*, int, char*, int); Expr *sqlite3ExprDup(sqlite3*,Expr*,int); ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); IdList *sqlite3IdListDup(sqlite3*,IdList*); Select *sqlite3SelectDup(sqlite3*,Select*,int); void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); | | | 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 | void sqlite3HaltConstraint(Parse*, int, char*, int); Expr *sqlite3ExprDup(sqlite3*,Expr*,int); ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int); SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); IdList *sqlite3IdListDup(sqlite3*,IdList*); Select *sqlite3SelectDup(sqlite3*,Select*,int); void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); void sqlite3RegisterBuiltinFunctions(sqlite3*); void sqlite3RegisterDateTimeFunctions(void); void sqlite3RegisterGlobalFunctions(void); int sqlite3SafetyCheckOk(sqlite3*); int sqlite3SafetyCheckSickOrOk(sqlite3*); void sqlite3ChangeCookie(Parse*, int); |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
1159 1160 1161 1162 1163 1164 1165 | assert( pPreStmt==0 ); nVar = sqlite3_bind_parameter_count(pStmt); nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *); pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte); memset(pPreStmt, 0, nByte); pPreStmt->pStmt = pStmt; | | | 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 | assert( pPreStmt==0 ); nVar = sqlite3_bind_parameter_count(pStmt); nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *); pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte); memset(pPreStmt, 0, nByte); pPreStmt->pStmt = pStmt; pPreStmt->nSql = (int)(*pzOut - zSql); pPreStmt->zSql = sqlite3_sql(pStmt); pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1]; #ifdef SQLITE_TEST if( pPreStmt->zSql==0 ){ char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1); memcpy(zCopy, zSql, pPreStmt->nSql); zCopy[pPreStmt->nSql] = '\0'; |
︙ | ︙ | |||
3466 3467 3468 3469 3470 3471 3472 | Tcl_AppendResult(interp,"unable to open file \"", argv[1], "\" for reading", 0); return TCL_ERROR; } MD5Init(&ctx); for(;;){ int n; | | | 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 | Tcl_AppendResult(interp,"unable to open file \"", argv[1], "\" for reading", 0); return TCL_ERROR; } MD5Init(&ctx); for(;;){ int n; n = (int)fread(zBuf, 1, sizeof(zBuf), in); if( n<=0 ) break; MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); } fclose(in); MD5Final(digest, &ctx); converter = (void(*)(unsigned char*,char*))cd; converter(digest, zBuf); |
︙ | ︙ | |||
3512 3513 3514 3515 3516 3517 3518 | if( p==0 ) return; if( !p->isInit ){ MD5Init(p); } for(i=0; i<argc; i++){ const char *zData = (char*)sqlite3_value_text(argv[i]); if( zData ){ | | | 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 | if( p==0 ) return; if( !p->isInit ){ MD5Init(p); } for(i=0; i<argc; i++){ const char *zData = (char*)sqlite3_value_text(argv[i]); if( zData ){ MD5Update(p, (unsigned char*)zData, (int)strlen(zData)); } } } static void md5finalize(sqlite3_context *context){ MD5Context *p; unsigned char digest[16]; char zBuf[33]; |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
796 797 798 799 800 801 802 | char *z; /* The space */ }; /* ** Append text to a dstr */ static void dstrAppend(struct dstr *p, const char *z, int divider){ | | | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | char *z; /* The space */ }; /* ** Append text to a dstr */ static void dstrAppend(struct dstr *p, const char *z, int divider){ int n = (int)strlen(z); if( p->nUsed + n + 2 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + n + 200; zNew = sqlite3_realloc(p->z, p->nAlloc); if( zNew==0 ){ sqlite3_free(p->z); memset(p, 0, sizeof(*p)); |
︙ | ︙ | |||
3623 3624 3625 3626 3627 3628 3629 | if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); Tcl_ResetResult(interp); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( zTail && objc>=5 ){ if( bytes>=0 ){ | | | | 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 | if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); Tcl_ResetResult(interp); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( zTail && objc>=5 ){ if( bytes>=0 ){ bytes = bytes - (int)(zTail-zSql); } if( (int)strlen(zTail)<bytes ){ bytes = (int)strlen(zTail); } Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); } if( rc!=SQLITE_OK ){ assert( pStmt==0 ); sprintf(zBuf, "(%d) ", rc); Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); |
︙ | ︙ | |||
3681 3682 3683 3684 3685 3686 3687 | rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); assert(rc==SQLITE_OK || pStmt==0); Tcl_ResetResult(interp); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( zTail && objc>=5 ){ if( bytes>=0 ){ | | | 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 | rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); assert(rc==SQLITE_OK || pStmt==0); Tcl_ResetResult(interp); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( zTail && objc>=5 ){ if( bytes>=0 ){ bytes = bytes - (int)(zTail-zSql); } Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); } if( rc!=SQLITE_OK ){ assert( pStmt==0 ); sprintf(zBuf, "(%d) ", rc); Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); |
︙ | ︙ | |||
3782 3783 3784 3785 3786 3787 3788 | if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( rc ){ return TCL_ERROR; } if( objc>=5 ){ if( zTail ){ | | | 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 | if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( rc ){ return TCL_ERROR; } if( objc>=5 ){ if( zTail ){ objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); }else{ objlen = 0; } pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); Tcl_IncrRefCount(pTail); Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); Tcl_DecrRefCount(pTail); |
︙ | ︙ | |||
3842 3843 3844 3845 3846 3847 3848 | if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( rc ){ return TCL_ERROR; } if( objc>=5 ){ if( zTail ){ | | | 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 | if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; if( rc ){ return TCL_ERROR; } if( objc>=5 ){ if( zTail ){ objlen = objlen - (int)((u8 *)zTail-(u8 *)zSql); }else{ objlen = 0; } pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen); Tcl_IncrRefCount(pTail); Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0); Tcl_DecrRefCount(pTail); |
︙ | ︙ |
Changes to src/test2.c.
︙ | ︙ | |||
543 544 545 546 547 548 549 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N-MEGABYTES FILE\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; pVfs = sqlite3_vfs_find(0); | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N-MEGABYTES FILE\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; pVfs = sqlite3_vfs_find(0); nFile = (int)strlen(argv[2]); zFile = sqlite3_malloc( nFile+2 ); if( zFile==0 ) return TCL_ERROR; memcpy(zFile, argv[2], nFile+1); zFile[nFile+1] = 0; rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd, (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 ); |
︙ | ︙ |
Changes to src/test3.c.
︙ | ︙ | |||
76 77 78 79 80 81 82 | if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; nRefSqlite3++; if( nRefSqlite3==1 ){ sDb.pVfs = sqlite3_vfs_find(0); sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; nRefSqlite3++; if( nRefSqlite3==1 ){ sDb.pVfs = sqlite3_vfs_find(0); sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } n = (int)strlen(argv[1]); zFilename = sqlite3_malloc( n+2 ); if( zFilename==0 ) return TCL_ERROR; memcpy(zFilename, argv[1], n+1); zFilename[n+1] = 0; rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); sqlite3_free(zFilename); |
︙ | ︙ |
Changes to src/test6.c.
︙ | ︙ | |||
464 465 466 467 468 469 470 | */ static int cfSync(sqlite3_file *pFile, int flags){ CrashFile *pCrash = (CrashFile *)pFile; int isCrash = 0; const char *zName = pCrash->zName; const char *zCrashFile = g.zCrashFile; | | | | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | */ static int cfSync(sqlite3_file *pFile, int flags){ CrashFile *pCrash = (CrashFile *)pFile; int isCrash = 0; const char *zName = pCrash->zName; const char *zCrashFile = g.zCrashFile; int nName = (int)strlen(zName); int nCrashFile = (int)strlen(zCrashFile); if( nCrashFile>0 && zCrashFile[nCrashFile-1]=='*' ){ nCrashFile--; if( nName>nCrashFile ) nName = nCrashFile; } #ifdef TRACE_CRASHTEST |
︙ | ︙ |
Changes to src/test8.c.
︙ | ︙ | |||
188 189 190 191 192 193 194 | nBytes = sizeof(char *) * nCol; for(ii=0; ii<nCol; ii++){ const char *zName = sqlite3_column_name(pStmt, ii); if( !zName ){ rc = SQLITE_NOMEM; goto out; } | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | nBytes = sizeof(char *) * nCol; for(ii=0; ii<nCol; ii++){ const char *zName = sqlite3_column_name(pStmt, ii); if( !zName ){ rc = SQLITE_NOMEM; goto out; } nBytes += (int)strlen(zName)+1; } aCol = (char **)sqlite3MallocZero(nBytes); if( !aCol ){ rc = SQLITE_NOMEM; goto out; } |
︙ | ︙ | |||
1213 1214 1215 1216 1217 1218 1219 | echo_vtab *p = (echo_vtab *)vtab; if( simulateVtabError(p, "xRename") ){ return SQLITE_ERROR; } if( p->isPattern ){ | | | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 | echo_vtab *p = (echo_vtab *)vtab; if( simulateVtabError(p, "xRename") ){ return SQLITE_ERROR; } if( p->isPattern ){ int nThis = (int)strlen(p->zThis); char *zSql = sqlite3_mprintf("ALTER TABLE %s RENAME TO %s%s", p->zTableName, zNewName, &p->zTableName[nThis] ); rc = sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
415 416 417 418 419 420 421 422 423 424 425 426 427 428 | #endif #ifdef SQLITE_ENABLE_RTREE Tcl_SetVar2(interp, "sqlite_options", "rtree", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY); #endif | > > > > > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | #endif #ifdef SQLITE_ENABLE_RTREE Tcl_SetVar2(interp, "sqlite_options", "rtree", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rtree", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_RTREE_INT_ONLY Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "rtree_int_only", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_SCHEMA_PRAGMAS Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ |
Changes to src/test_func.c.
︙ | ︙ | |||
198 199 200 201 202 203 204 | char *zAux = sqlite3_get_auxdata(pCtx, i); if( zAux ){ zRet[i*2] = '1'; assert( strcmp(zAux,z)==0 ); }else { zRet[i*2] = '0'; } | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | char *zAux = sqlite3_get_auxdata(pCtx, i); if( zAux ){ zRet[i*2] = '1'; assert( strcmp(zAux,z)==0 ); }else { zRet[i*2] = '0'; } n = (int)strlen(z) + 1; zAux = testContextMalloc(pCtx, n); if( zAux ){ memcpy(zAux, z, n); sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); } zRet[i*2+1] = ' '; } |
︙ | ︙ |
Changes to src/test_fuzzer.c.
︙ | ︙ | |||
304 305 306 307 308 309 310 | int rc = SQLITE_OK; /* Return code */ int nFrom; /* Size of string zFrom, in bytes */ int nTo; /* Size of string zTo, in bytes */ fuzzer_rule *pRule = 0; /* New rule object to return */ if( zFrom==0 ) zFrom = ""; if( zTo==0 ) zTo = ""; | | | | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | int rc = SQLITE_OK; /* Return code */ int nFrom; /* Size of string zFrom, in bytes */ int nTo; /* Size of string zTo, in bytes */ fuzzer_rule *pRule = 0; /* New rule object to return */ if( zFrom==0 ) zFrom = ""; if( zTo==0 ) zTo = ""; nFrom = (int)strlen(zFrom); nTo = (int)strlen(zTo); /* Silently ignore null transformations */ if( strcmp(zFrom, zTo)==0 ){ *ppRule = 0; return SQLITE_OK; } |
︙ | ︙ | |||
444 445 446 447 448 449 450 | ** [pqr] becomes pqr ** `mno` becomes mno */ static char *fuzzerDequote(const char *zIn){ int nIn; /* Size of input string, in bytes */ char *zOut; /* Output (dequoted) string */ | | | | 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | ** [pqr] becomes pqr ** `mno` becomes mno */ static char *fuzzerDequote(const char *zIn){ int nIn; /* Size of input string, in bytes */ char *zOut; /* Output (dequoted) string */ nIn = (int)strlen(zIn); zOut = sqlite3_malloc(nIn+1); if( zOut ){ char q = zIn[0]; /* Quote character (if any ) */ if( q!='[' && q!= '\'' && q!='"' && q!='`' ){ memcpy(zOut, zIn, nIn+1); }else{ int iOut = 0; /* Index of next byte to write to output */ int iIn; /* Index of next byte to read from input */ if( q=='[' ) q = ']'; for(iIn=1; iIn<nIn; iIn++){ if( zIn[iIn]==q ) iIn++; zOut[iOut++] = zIn[iIn]; } } assert( (int)strlen(zOut)<=nIn ); } return zOut; } /* ** xDisconnect/xDestroy method for the fuzzer module. */ |
︙ | ︙ | |||
509 510 511 512 513 514 515 | *pzErr = sqlite3_mprintf( "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule ); rc = SQLITE_ERROR; }else{ int nModule; /* Length of zModule, in bytes */ | | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | *pzErr = sqlite3_mprintf( "%s: wrong number of CREATE VIRTUAL TABLE arguments", zModule ); rc = SQLITE_ERROR; }else{ int nModule; /* Length of zModule, in bytes */ nModule = (int)strlen(zModule); pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1); if( pNew==0 ){ rc = SQLITE_NOMEM; }else{ char *zTab; /* Dequoted name of fuzzer data table */ memset(pNew, 0, sizeof(*pNew)); |
︙ | ︙ | |||
866 867 868 869 870 871 872 | const char *zWord, fuzzer_cost rBaseCost ){ fuzzer_stem *pNew; fuzzer_rule *pRule; unsigned int h; | | | | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 | const char *zWord, fuzzer_cost rBaseCost ){ fuzzer_stem *pNew; fuzzer_rule *pRule; unsigned int h; pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 ); if( pNew==0 ) return 0; memset(pNew, 0, sizeof(*pNew)); pNew->zBasis = (char*)&pNew[1]; pNew->nBasis = (int)strlen(zWord); memcpy(pNew->zBasis, zWord, pNew->nBasis+1); pRule = pCur->pVtab->pRule; while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){ pRule = pRule->pNext; } pNew->pRule = pRule; pNew->n = -1; |
︙ | ︙ | |||
993 994 995 996 997 998 999 | pCur->nullRule.nTo = 0; pCur->nullRule.zFrom = ""; pCur->iRowid = 1; assert( pCur->pStem==0 ); /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this ** query will return zero rows. */ | | | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 | pCur->nullRule.nTo = 0; pCur->nullRule.zFrom = ""; pCur->iRowid = 1; assert( pCur->pStem==0 ); /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this ** query will return zero rows. */ if( (int)strlen(zWord)<FUZZER_MX_OUTPUT_LENGTH ){ pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0); if( pStem==0 ) return SQLITE_NOMEM; pStem->pRule = &pCur->nullRule; pStem->n = pStem->nBasis; }else{ pCur->rLimit = 0; } |
︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 | } pIdxInfo->estimatedCost = (double)10000; return SQLITE_OK; } /* | | < | 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | } pIdxInfo->estimatedCost = (double)10000; return SQLITE_OK; } /* ** A virtual table module that implements the "fuzzer". */ static sqlite3_module fuzzerModule = { 0, /* iVersion */ fuzzerConnect, fuzzerConnect, fuzzerBestIndex, fuzzerDisconnect, |
︙ | ︙ |
Changes to src/test_hexio.c.
︙ | ︙ | |||
122 123 124 125 126 127 128 | in = fopen(zFile, "r"); } if( in==0 ){ Tcl_AppendResult(interp, "cannot open input file ", zFile, 0); return TCL_ERROR; } fseek(in, offset, SEEK_SET); | | | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | in = fopen(zFile, "r"); } if( in==0 ){ Tcl_AppendResult(interp, "cannot open input file ", zFile, 0); return TCL_ERROR; } fseek(in, offset, SEEK_SET); got = (int)fread(zBuf, 1, amt, in); fclose(in); if( got<0 ){ got = 0; } sqlite3TestBinToHex(zBuf, got); Tcl_AppendResult(interp, zBuf, 0); sqlite3_free(zBuf); |
︙ | ︙ | |||
174 175 176 177 178 179 180 | out = fopen(zFile, "r+"); } if( out==0 ){ Tcl_AppendResult(interp, "cannot open output file ", zFile, 0); return TCL_ERROR; } fseek(out, offset, SEEK_SET); | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | out = fopen(zFile, "r+"); } if( out==0 ){ Tcl_AppendResult(interp, "cannot open output file ", zFile, 0); return TCL_ERROR; } fseek(out, offset, SEEK_SET); written = (int)fwrite(aOut, 1, nOut, out); sqlite3_free(aOut); fclose(out); Tcl_SetObjResult(interp, Tcl_NewIntObj(written)); return TCL_OK; } /* |
︙ | ︙ |
Changes to src/test_journal.c.
︙ | ︙ | |||
286 287 288 289 290 291 292 | ** ** c) There is currently a reserved lock on the file. **/ static jt_file *locateDatabaseHandle(const char *zJournal){ jt_file *pMain = 0; enterJtMutex(); for(pMain=g.pList; pMain; pMain=pMain->pNext){ | | | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | ** ** c) There is currently a reserved lock on the file. **/ static jt_file *locateDatabaseHandle(const char *zJournal){ jt_file *pMain = 0; enterJtMutex(); for(pMain=g.pList; pMain; pMain=pMain->pNext){ int nName = (int)(strlen(zJournal) - strlen("-journal")); if( (pMain->flags&SQLITE_OPEN_MAIN_DB) && ((int)strlen(pMain->zName)==nName) && 0==memcmp(pMain->zName, zJournal, nName) && (pMain->eLock>=SQLITE_LOCK_RESERVED) ){ break; } } leaveJtMutex(); |
︙ | ︙ | |||
719 720 721 722 723 724 725 | /* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before ** returning. */ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ | | | 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 | /* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before ** returning. */ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int nPath = (int)strlen(zPath); if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ /* Deleting a journal file. The end of a transaction. */ jt_file *pMain = locateDatabaseHandle(zPath); if( pMain ){ closeTransaction(pMain); } } |
︙ | ︙ |
Changes to src/test_multiplex.c.
︙ | ︙ | |||
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | #ifdef SQLITE_ENABLE_8_3_NAMES /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are ** part of a database journal are named db.401, db.402, and so on. A ** database may therefore not grow to larger than 400 chunks. Attempting ** to open chunk 401 indicates the database is full. */ if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ *rc = SQLITE_FULL; return 0; } #endif *rc = multiplexSubFilename(pGroup, iChunk); if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){ int flags, bExists; flags = pGroup->flags; if( createFlag ){ flags |= SQLITE_OPEN_CREATE; }else if( iChunk==0 ){ /* Fall through */ }else if( pGroup->aReal[iChunk].z==0 ){ return 0; }else{ *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists); | > | > > > > > > > > | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | #ifdef SQLITE_ENABLE_8_3_NAMES /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are ** part of a database journal are named db.401, db.402, and so on. A ** database may therefore not grow to larger than 400 chunks. Attempting ** to open chunk 401 indicates the database is full. */ if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){ sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName); *rc = SQLITE_FULL; return 0; } #endif *rc = multiplexSubFilename(pGroup, iChunk); if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){ int flags, bExists; flags = pGroup->flags; if( createFlag ){ flags |= SQLITE_OPEN_CREATE; }else if( iChunk==0 ){ /* Fall through */ }else if( pGroup->aReal[iChunk].z==0 ){ return 0; }else{ *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists); if( *rc || !bExists ){ if( *rc ){ sqlite3_log(*rc, "multiplexor.xAccess failure on %s", pGroup->aReal[iChunk].z); } return 0; } flags &= ~SQLITE_OPEN_CREATE; } pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); if( pSubOpen==0 ){ *rc = SQLITE_IOERR_NOMEM; return 0; } pGroup->aReal[iChunk].p = pSubOpen; *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen, flags, pOutFlags); if( (*rc)!=SQLITE_OK ){ sqlite3_log(*rc, "multiplexor.xOpen failure on %s", pGroup->aReal[iChunk].z); sqlite3_free(pSubOpen); pGroup->aReal[iChunk].p = 0; return 0; } } return pSubOpen; } |
︙ | ︙ | |||
637 638 639 640 641 642 643 | int rc; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir); if( rc==SQLITE_OK ){ /* If the main chunk was deleted successfully, also delete any subsequent ** chunks - starting with the last (highest numbered). */ | | | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 | int rc; sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir); if( rc==SQLITE_OK ){ /* If the main chunk was deleted successfully, also delete any subsequent ** chunks - starting with the last (highest numbered). */ int nName = (int)strlen(zName); char *z; z = sqlite3_malloc(nName + 5); if( z==0 ){ rc = SQLITE_IOERR_NOMEM; }else{ int iChunk = 0; int bExists; |
︙ | ︙ |
Changes to src/test_onefile.c.
︙ | ︙ | |||
602 603 604 605 606 607 608 | } eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE); p->base.pMethods = &fs_io_methods; p->eType = eType; assert(strlen("-journal")==8); | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | } eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE); p->base.pMethods = &fs_io_methods; p->eType = eType; assert(strlen("-journal")==8); nName = (int)strlen(zName)-((eType==JOURNAL_FILE)?8:0); pReal=pFsVfs->pFileList; for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext); if( !pReal ){ int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB; sqlite3_int64 size; sqlite3_file *pRealFile; |
︙ | ︙ | |||
683 684 685 686 687 688 689 | ** returning. */ static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int rc = SQLITE_OK; fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; fs_real_file *pReal; sqlite3_file *pF; | | | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | ** returning. */ static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int rc = SQLITE_OK; fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; fs_real_file *pReal; sqlite3_file *pF; int nName = (int)strlen(zPath) - 8; assert(strlen("-journal")==8); assert(strcmp("-journal", &zPath[nName])==0); pReal = pFsVfs->pFileList; for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext); if( pReal ){ |
︙ | ︙ | |||
713 714 715 716 717 718 719 | const char *zPath, int flags, int *pResOut ){ fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; fs_real_file *pReal; int isJournal = 0; | | | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | const char *zPath, int flags, int *pResOut ){ fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs; fs_real_file *pReal; int isJournal = 0; int nName = (int)strlen(zPath); if( flags!=SQLITE_ACCESS_EXISTS ){ sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent; return pParent->xAccess(pParent, zPath, flags, pResOut); } assert(strlen("-journal")==8); |
︙ | ︙ |
Changes to src/test_osinst.c.
︙ | ︙ | |||
667 668 669 670 671 672 673 | put32bits(&zRec[20], offset); p->nBuf += 24; } static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){ VfslogVfs *p = (VfslogVfs *)pVfs; unsigned char *zRec; | | | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | put32bits(&zRec[20], offset); p->nBuf += 24; } static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){ VfslogVfs *p = (VfslogVfs *)pVfs; unsigned char *zRec; int nStr = zStr ? (int)strlen(zStr) : 0; if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){ vfslog_flush(p); } zRec = (unsigned char *)&p->aBuf[p->nBuf]; put32bits(&zRec[0], nStr); if( zStr ){ memcpy(&zRec[4], zStr, nStr); |
︙ | ︙ | |||
716 717 718 719 720 721 722 | int nVfs; pParent = sqlite3_vfs_find(zParentVfs); if( !pParent ){ return SQLITE_ERROR; } | | | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | int nVfs; pParent = sqlite3_vfs_find(zParentVfs); if( !pParent ){ return SQLITE_ERROR; } nVfs = (int)strlen(zVfs); nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1; p = (VfslogVfs *)sqlite3_malloc(nByte); memset(p, 0, nByte); p->pVfs = pParent; p->pLog = (sqlite3_file *)&p[1]; memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs)); |
︙ | ︙ |
Changes to src/test_quota.c.
︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 125 126 127 128 129 | ** open file. This object is opaque to all users - the internal ** structure is only visible to the functions below. */ struct quota_FILE { FILE *f; /* Open stdio file pointer */ sqlite3_int64 iOfst; /* Current offset into the file */ quotaFile *pFile; /* The file record in the quota system */ }; /************************* Global Variables **********************************/ /* ** All global variables used by this file are containing within the following ** gQuota structure. | > > > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | ** open file. This object is opaque to all users - the internal ** structure is only visible to the functions below. */ struct quota_FILE { FILE *f; /* Open stdio file pointer */ sqlite3_int64 iOfst; /* Current offset into the file */ quotaFile *pFile; /* The file record in the quota system */ #if SQLITE_OS_WIN char *zMbcsName; /* Full MBCS pathname of the file */ #endif }; /************************* Global Variables **********************************/ /* ** All global variables used by this file are containing within the following ** gQuota structure. |
︙ | ︙ | |||
337 338 339 340 341 342 343 | int createFlag /* Try to create the file if not found */ ){ quotaFile *pFile = pGroup->pFiles; while( pFile && strcmp(pFile->zFilename, zName)!=0 ){ pFile = pFile->pNext; } if( pFile==0 && createFlag ){ | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | int createFlag /* Try to create the file if not found */ ){ quotaFile *pFile = pGroup->pFiles; while( pFile && strcmp(pFile->zFilename, zName)!=0 ){ pFile = pFile->pNext; } if( pFile==0 && createFlag ){ int nName = (int)(strlen(zName) & 0x3fffffff); pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 ); if( pFile ){ memset(pFile, 0, sizeof(*pFile)); pFile->zFilename = (char*)&pFile[1]; memcpy(pFile->zFilename, zName, nName+1); pFile->pNext = pGroup->pFiles; if( pGroup->pFiles ) pGroup->pFiles->ppPrev = &pFile->pNext; |
︙ | ︙ | |||
415 416 417 418 419 420 421 | /* ** Translate UTF8 to MBCS for use in fopen() calls. Return a pointer to the ** translated text.. Call quota_mbcs_free() to deallocate any memory ** used to store the returned pointer when done. */ static char *quota_utf8_to_mbcs(const char *zUtf8){ #if SQLITE_OS_WIN | | | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 | /* ** Translate UTF8 to MBCS for use in fopen() calls. Return a pointer to the ** translated text.. Call quota_mbcs_free() to deallocate any memory ** used to store the returned pointer when done. */ static char *quota_utf8_to_mbcs(const char *zUtf8){ #if SQLITE_OS_WIN size_t n; /* Bytes in zUtf8 */ int nWide; /* number of UTF-16 characters */ int nMbcs; /* Bytes of MBCS */ LPWSTR zTmpWide; /* The UTF16 text */ char *zMbcs; /* The MBCS text */ int codepage; /* Code page used by fopen() */ n = strlen(zUtf8); |
︙ | ︙ | |||
893 894 895 896 897 898 899 | quotaGroup *pGroup; quotaEnter(); pGroup = gQuota.pGroup; while( pGroup && strcmp(pGroup->zPattern, zPattern)!=0 ){ pGroup = pGroup->pNext; } if( pGroup==0 ){ | | | 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 | quotaGroup *pGroup; quotaEnter(); pGroup = gQuota.pGroup; while( pGroup && strcmp(pGroup->zPattern, zPattern)!=0 ){ pGroup = pGroup->pNext; } if( pGroup==0 ){ int nPattern = (int)(strlen(zPattern) & 0x3fffffff); if( iLimit<=0 ){ quotaLeave(); return SQLITE_OK; } pGroup = (quotaGroup *)sqlite3_malloc( sizeof(*pGroup) + nPattern + 1 ); if( pGroup==0 ){ quotaLeave(); |
︙ | ︙ | |||
975 976 977 978 979 980 981 | /* ** Open a potentially quotaed file for I/O. */ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ quota_FILE *p = 0; char *zFull = 0; | | < > > > > | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | /* ** Open a potentially quotaed file for I/O. */ quota_FILE *sqlite3_quota_fopen(const char *zFilename, const char *zMode){ quota_FILE *p = 0; char *zFull = 0; char *zFullTranslated = 0; int rc; quotaGroup *pGroup; quotaFile *pFile; zFull = (char*)sqlite3_malloc(gQuota.sThisVfs.mxPathname + 1); if( zFull==0 ) return 0; rc = gQuota.pOrigVfs->xFullPathname(gQuota.pOrigVfs, zFilename, gQuota.sThisVfs.mxPathname+1, zFull); if( rc ) goto quota_fopen_error; p = (quota_FILE*)sqlite3_malloc(sizeof(*p)); if( p==0 ) goto quota_fopen_error; memset(p, 0, sizeof(*p)); zFullTranslated = quota_utf8_to_mbcs(zFull); if( zFullTranslated==0 ) goto quota_fopen_error; p->f = fopen(zFullTranslated, zMode); if( p->f==0 ) goto quota_fopen_error; quotaEnter(); pGroup = quotaGroupFind(zFull); if( pGroup ){ pFile = quotaFindFile(pGroup, zFull, 1); if( pFile==0 ){ quotaLeave(); goto quota_fopen_error; } pFile->nRef++; p->pFile = pFile; } quotaLeave(); sqlite3_free(zFull); #if SQLITE_OS_WIN p->zMbcsName = zFullTranslated; #endif return p; quota_fopen_error: quota_mbcs_free(zFullTranslated); sqlite3_free(zFull); if( p && p->f ) fclose(p->f); sqlite3_free(p); return 0; } /* |
︙ | ︙ | |||
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | size_t nmemb, /* Number of elements */ quota_FILE *p /* Write to this quota_FILE objecct */ ){ sqlite3_int64 iOfst; sqlite3_int64 iEnd; sqlite3_int64 szNew; quotaFile *pFile; iOfst = ftell(p->f); iEnd = iOfst + size*nmemb; pFile = p->pFile; if( pFile && pFile->iSize<iEnd ){ quotaGroup *pGroup = pFile->pGroup; quotaEnter(); | > | 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 | size_t nmemb, /* Number of elements */ quota_FILE *p /* Write to this quota_FILE objecct */ ){ sqlite3_int64 iOfst; sqlite3_int64 iEnd; sqlite3_int64 szNew; quotaFile *pFile; size_t rc; iOfst = ftell(p->f); iEnd = iOfst + size*nmemb; pFile = p->pFile; if( pFile && pFile->iSize<iEnd ){ quotaGroup *pGroup = pFile->pGroup; quotaEnter(); |
︙ | ︙ | |||
1064 1065 1066 1067 1068 1069 1070 1071 | iEnd = iOfst + size*nmemb; szNew = pGroup->iSize - pFile->iSize + iEnd; } } pGroup->iSize = szNew; pFile->iSize = iEnd; quotaLeave(); } | > > | > > > > > > > > > > > > > | 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 | iEnd = iOfst + size*nmemb; szNew = pGroup->iSize - pFile->iSize + iEnd; } } pGroup->iSize = szNew; pFile->iSize = iEnd; quotaLeave(); }else{ pFile = 0; } rc = fwrite(pBuf, size, nmemb, p->f); /* If the write was incomplete, adjust the file size and group size ** downward */ if( rc<nmemb && pFile ){ size_t nWritten = rc>=0 ? rc : 0; sqlite3_int64 iNewEnd = iOfst + size*nWritten; if( iNewEnd<iEnd ) iNewEnd = iEnd; quotaEnter(); pFile->pGroup->iSize += iNewEnd - pFile->iSize; pFile->iSize = iNewEnd; quotaLeave(); } return rc; } /* ** Close an open quota_FILE stream. */ int sqlite3_quota_fclose(quota_FILE *p){ int rc; |
︙ | ︙ | |||
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 | gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0); quotaRemoveFile(pFile); } quotaGroupDeref(pGroup); } quotaLeave(); } sqlite3_free(p); return rc; } /* ** Flush memory buffers for a quota_FILE to disk. */ | > > > | 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | gQuota.pOrigVfs->xDelete(gQuota.pOrigVfs, pFile->zFilename, 0); quotaRemoveFile(pFile); } quotaGroupDeref(pGroup); } quotaLeave(); } #if SQLITE_OS_WIN quota_mbcs_free(p->zMbcsName); #endif sqlite3_free(p); return rc; } /* ** Flush memory buffers for a quota_FILE to disk. */ |
︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | /* ** Tell the current location of a quota_FILE stream. */ long sqlite3_quota_ftell(quota_FILE *p){ return ftell(p->f); } /* ** Remove a managed file. Update quotas accordingly. */ int sqlite3_quota_remove(const char *zFilename){ char *zFull; /* Full pathname for zFilename */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | /* ** Tell the current location of a quota_FILE stream. */ long sqlite3_quota_ftell(quota_FILE *p){ return ftell(p->f); } /* ** Truncate a file to szNew bytes. */ int sqlite3_quota_ftruncate(quota_FILE *p, sqlite3_int64 szNew){ quotaFile *pFile = p->pFile; int rc; if( (pFile = p->pFile)!=0 && pFile->iSize<szNew ){ quotaGroup *pGroup; if( pFile->iSize<szNew ){ /* This routine cannot be used to extend a file that is under ** quota management. Only true truncation is allowed. */ return -1; } pGroup = pFile->pGroup; quotaEnter(); pGroup->iSize += szNew - pFile->iSize; quotaLeave(); } #if SQLITE_OS_UNIX rc = ftruncate(fileno(p->f), szNew); #endif #if SQLITE_OS_WIN rc = _chsize_s(_fileno(p->f), szNew); #endif if( pFile && rc==0 ){ quotaGroup *pGroup = pFile->pGroup; quotaEnter(); pGroup->iSize += szNew - pFile->iSize; pFile->iSize = szNew; quotaLeave(); } return rc; } /* ** Determine the time that the given file was last modified, in ** seconds size 1970. Write the result into *pTime. Return 0 on ** success and non-zero on any kind of error. */ int sqlite3_quota_file_mtime(quota_FILE *p, time_t *pTime){ int rc; #if SQLITE_OS_UNIX struct stat buf; rc = fstat(fileno(p->f), &buf); #endif #if SQLITE_OS_WIN struct _stati64 buf; rc = _stati64(p->zMbcsName, &buf); #endif if( rc==0 ) *pTime = buf.st_mtime; return rc; } /* ** Return the true size of the file, as reported by the operating ** system. */ sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE *p){ int rc; #if SQLITE_OS_UNIX struct stat buf; rc = fstat(fileno(p->f), &buf); #endif #if SQLITE_OS_WIN struct _stati64 buf; rc = _stati64(p->zMbcsName, &buf); #endif return rc==0 ? buf.st_size : -1; } /* ** Return the size of the file, as it is known to the quota subsystem. */ sqlite3_int64 sqlite3_quota_file_size(quota_FILE *p){ return p->pFile ? p->pFile->iSize : -1; } /* ** Remove a managed file. Update quotas accordingly. */ int sqlite3_quota_remove(const char *zFilename){ char *zFull; /* Full pathname for zFilename */ size_t nFull; /* Number of bytes in zFilename */ int rc; /* Result code */ quotaGroup *pGroup; /* Group containing zFilename */ quotaFile *pFile; /* A file in the group */ quotaFile *pNextFile; /* next file in the group */ int diff; /* Difference between filenames */ char c; /* First character past end of pattern */ |
︙ | ︙ | |||
1476 1477 1478 1479 1480 1481 1482 | int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; char *zBuf; int sz; int nElem; | | | 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 | int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; char *zBuf; int sz; int nElem; size_t got; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR; |
︙ | ︙ | |||
1511 1512 1513 1514 1515 1516 1517 | int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; char *zBuf; int sz; int nElem; | | | | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 | int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; char *zBuf; int sz; int nElem; size_t got; if( objc!=5 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE NELEM CONTENT"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[3], &nElem) ) return TCL_ERROR; zBuf = Tcl_GetString(objv[4]); got = sqlite3_quota_fwrite(zBuf, sz, nElem, p); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(got)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_fclose HANDLE */ static int test_quota_fclose( |
︙ | ︙ | |||
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); x = sqlite3_quota_ftell(p); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_remove FILENAME */ static int test_quota_remove( void * clientData, Tcl_Interp *interp, | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); x = sqlite3_quota_ftell(p); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_ftruncate HANDLE SIZE */ static int test_quota_ftruncate( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; sqlite3_int64 x; Tcl_WideInt w; int rc; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE SIZE"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); if( Tcl_GetWideIntFromObj(interp, objv[2], &w) ) return TCL_ERROR; x = (sqlite3_int64)w; rc = sqlite3_quota_ftruncate(p, x); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_file_size HANDLE */ static int test_quota_file_size( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; sqlite3_int64 x; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); x = sqlite3_quota_file_size(p); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_file_truesize HANDLE */ static int test_quota_file_truesize( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; sqlite3_int64 x; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); x = sqlite3_quota_file_truesize(p); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(x)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_file_mtime HANDLE */ static int test_quota_file_mtime( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ quota_FILE *p; time_t t; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "HANDLE"); return TCL_ERROR; } p = sqlite3TestTextToPtr(Tcl_GetString(objv[1])); t = 0; sqlite3_quota_file_mtime(p, &t); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); return TCL_OK; } /* ** tclcmd: sqlite3_quota_remove FILENAME */ static int test_quota_remove( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
1709 1710 1711 1712 1713 1714 1715 | ** of this module. */ int Sqlitequota_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { | | | | | | | | | | | | | | > > > > | | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 | ** of this module. */ int Sqlitequota_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; } aCmd[] = { { "sqlite3_quota_initialize", test_quota_initialize }, { "sqlite3_quota_shutdown", test_quota_shutdown }, { "sqlite3_quota_set", test_quota_set }, { "sqlite3_quota_file", test_quota_file }, { "sqlite3_quota_dump", test_quota_dump }, { "sqlite3_quota_fopen", test_quota_fopen }, { "sqlite3_quota_fread", test_quota_fread }, { "sqlite3_quota_fwrite", test_quota_fwrite }, { "sqlite3_quota_fclose", test_quota_fclose }, { "sqlite3_quota_fflush", test_quota_fflush }, { "sqlite3_quota_fseek", test_quota_fseek }, { "sqlite3_quota_rewind", test_quota_rewind }, { "sqlite3_quota_ftell", test_quota_ftell }, { "sqlite3_quota_ftruncate", test_quota_ftruncate }, { "sqlite3_quota_file_size", test_quota_file_size }, { "sqlite3_quota_file_truesize", test_quota_file_truesize }, { "sqlite3_quota_file_mtime", test_quota_file_mtime }, { "sqlite3_quota_remove", test_quota_remove }, { "sqlite3_quota_glob", test_quota_glob }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); } return TCL_OK; } #endif |
Changes to src/test_quota.h.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** callback does enlarge the quota such that the total size of all ** files within the group is less than the new quota, then the write ** continues as if nothing had happened. */ #ifndef _QUOTA_H_ #include "sqlite3.h" #include <stdio.h> /* Make this callable from C++ */ #ifdef __cplusplus extern "C" { #endif /* | > > > > > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** callback does enlarge the quota such that the total size of all ** files within the group is less than the new quota, then the write ** continues as if nothing had happened. */ #ifndef _QUOTA_H_ #include "sqlite3.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #if SQLITE_OS_UNIX # include <unistd.h> #endif #if SQLITE_OS_WIN # include <windows.h> #endif /* Make this callable from C++ */ #ifdef __cplusplus extern "C" { #endif /* |
︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 | ** Move the read/write pointer for a quota_FILE object. Or tell the ** current location of the read/write pointer. */ int sqlite3_quota_fseek(quota_FILE*, long, int); void sqlite3_quota_rewind(quota_FILE*); long sqlite3_quota_ftell(quota_FILE*); /* ** Delete a file from the disk, if that file is under quota management. ** Adjust quotas accordingly. ** ** If zFilename is the name of a directory that matches one of the ** quota glob patterns, then all files under quota management that ** are contained within that directory are deleted. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | ** Move the read/write pointer for a quota_FILE object. Or tell the ** current location of the read/write pointer. */ int sqlite3_quota_fseek(quota_FILE*, long, int); void sqlite3_quota_rewind(quota_FILE*); long sqlite3_quota_ftell(quota_FILE*); /* ** Truncate a file previously opened by sqlite3_quota_fopen(). Return ** zero on success and non-zero on any kind of failure. ** ** The newSize argument must be less than or equal to the current file size. ** Any attempt to "truncate" a file to a larger size results in ** undefined behavior. */ int sqlite3_quota_ftrunate(quota_FILE*, sqlite3_int64 newSize); /* ** Return the last modification time of the opened file, in seconds ** since 1970. */ int sqlite3_quota_file_mtime(quota_FILE*, time_t *pTime); /* ** Return the size of the file as it is known to the quota system. ** ** This size might be different from the true size of the file on ** disk if some outside process has modified the file without using the ** quota mechanism, or if calls to sqlite3_quota_fwrite() have occurred ** which have increased the file size, but those writes have not yet been ** forced to disk using sqlite3_quota_fflush(). ** ** Return -1 if the file is not participating in quota management. */ sqlite3_int64 sqlite3_quota_file_size(quota_FILE*); /* ** Return the true size of the file. ** ** The true size should be the same as the size of the file as known ** to the quota system, however the sizes might be different if the ** file has been extended or truncated via some outside process or if ** pending writes have not yet been flushed to disk. ** ** Return -1 if the file does not exist or if the size of the file ** cannot be determined for some reason. */ sqlite3_int64 sqlite3_quota_file_truesize(quota_FILE*); /* ** Delete a file from the disk, if that file is under quota management. ** Adjust quotas accordingly. ** ** If zFilename is the name of a directory that matches one of the ** quota glob patterns, then all files under quota management that ** are contained within that directory are deleted. |
︙ | ︙ |
Changes to src/test_rtree.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /* ** Implementation of "circle" r-tree geometry callback. */ static int circle_geom( sqlite3_rtree_geometry *p, int nCoord, double *aCoord, int *pRes ){ int i; /* Iterator variable */ Circle *pCircle; /* Structure defining circular region */ double xmin, xmax; /* X dimensions of box being tested */ double ymin, ymax; /* X dimensions of box being tested */ | > > > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | /* ** Implementation of "circle" r-tree geometry callback. */ static int circle_geom( sqlite3_rtree_geometry *p, int nCoord, #ifdef SQLITE_RTREE_INT_ONLY sqlite3_int64 *aCoord, #else double *aCoord, #endif int *pRes ){ int i; /* Iterator variable */ Circle *pCircle; /* Structure defining circular region */ double xmin, xmax; /* X dimensions of box being tested */ double ymin, ymax; /* X dimensions of box being tested */ |
︙ | ︙ | |||
184 185 186 187 188 189 190 | ** ** cube(x, y, z, width, height, depth) ** ** The width, height and depth parameters must all be greater than zero. */ static int cube_geom( sqlite3_rtree_geometry *p, | | > > > > | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | ** ** cube(x, y, z, width, height, depth) ** ** The width, height and depth parameters must all be greater than zero. */ static int cube_geom( sqlite3_rtree_geometry *p, int nCoord, #ifdef SQLITE_RTREE_INT_ONLY sqlite3_int64 *aCoord, #else double *aCoord, #endif int *piRes ){ Cube *pCube = (Cube *)p->pUser; assert( p->pContext==(void *)&gHere ); if( pCube==0 ){ |
︙ | ︙ |
Changes to src/test_vfs.c.
︙ | ︙ | |||
780 781 782 783 784 785 786 | } /* Search for a TestvfsBuffer. Create a new one if required. */ for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; } if( !pBuffer ){ | | | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | } /* Search for a TestvfsBuffer. Create a new one if required. */ for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; } if( !pBuffer ){ int nByte = sizeof(TestvfsBuffer) + (int)strlen(pFd->zFilename) + 1; pBuffer = (TestvfsBuffer *)ckalloc(nByte); memset(pBuffer, 0, nByte); pBuffer->zFile = (char *)&pBuffer[1]; strcpy(pBuffer->zFile, pFd->zFilename); pBuffer->pNext = p->pBuffer; p->pBuffer = pBuffer; } |
︙ | ︙ | |||
862 863 864 865 866 867 868 | TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); int nLock; char zLock[80]; if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); | | | | 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); int nLock; char zLock[80]; if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); nLock = (int)strlen(zLock); if( flags & SQLITE_SHM_LOCK ){ strcpy(&zLock[nLock], " lock"); }else{ strcpy(&zLock[nLock], " unlock"); } nLock += (int)strlen(&zLock[nLock]); if( flags & SQLITE_SHM_SHARED ){ strcpy(&zLock[nLock], " shared"); }else{ strcpy(&zLock[nLock], " exclusive"); } tvfsExecTcl(p, "xShmLock", Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, |
︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 | } if( szOsFile<sizeof(TestvfsFile) ){ szOsFile = sizeof(TestvfsFile); } zVfs = Tcl_GetString(objv[1]); | | | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 | } if( szOsFile<sizeof(TestvfsFile) ){ szOsFile = sizeof(TestvfsFile); } zVfs = Tcl_GetString(objv[1]); nByte = sizeof(Testvfs) + (int)strlen(zVfs)+1; p = (Testvfs *)ckalloc(nByte); memset(p, 0, nByte); p->iDevchar = -1; p->iSectorsize = -1; /* Create the new object command before querying SQLite for a default VFS ** to use for 'real' IO operations. This is because creating the new VFS |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2730 2731 2732 2733 2734 2735 2736 | p->rc = rc = SQLITE_BUSY; goto vdbe_return; } db->isTransactionSavepoint = 0; rc = p->rc; }else{ iSavepoint = db->nSavepoint - iSavepoint - 1; | > | | > | 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 | p->rc = rc = SQLITE_BUSY; goto vdbe_return; } db->isTransactionSavepoint = 0; rc = p->rc; }else{ iSavepoint = db->nSavepoint - iSavepoint - 1; if( p1==SAVEPOINT_ROLLBACK ){ for(ii=0; ii<db->nDb; ii++){ sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT); } } for(ii=0; ii<db->nDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
1235 1236 1237 1238 1239 1240 1241 | */ if( pOp->p4type==P4_SUBPROGRAM ){ int nByte = (nSub+1)*sizeof(SubProgram*); int j; for(j=0; j<nSub; j++){ if( apSub[j]==pOp->p4.pProgram ) break; } | | | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 | */ if( pOp->p4type==P4_SUBPROGRAM ){ int nByte = (nSub+1)*sizeof(SubProgram*); int j; for(j=0; j<nSub; j++){ if( apSub[j]==pOp->p4.pProgram ) break; } if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ apSub = (SubProgram **)pSub->z; apSub[nSub++] = pOp->p4.pProgram; pSub->flags |= MEM_Blob; pSub->n = nSub*sizeof(SubProgram*); } } } |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
55 56 57 58 59 60 61 | #endif } /* ** Make sure pMem->z points to a writable allocation of at least ** n bytes. ** | < | > | | > > > > | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #endif } /* ** Make sure pMem->z points to a writable allocation of at least ** n bytes. ** ** If the third argument passed to this function is true, then memory ** cell pMem must contain a string or blob. In this case the content is ** preserved. Otherwise, if the third parameter to this function is false, ** any current string or blob value may be discarded. ** ** This function sets the MEM_Dyn flag and clears any xDel callback. ** It also clears MEM_Ephem and MEM_Static. If the preserve flag is ** not set, Mem.n is zeroed. */ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ assert( 1 >= ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) + (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + ((pMem->flags&MEM_Ephem) ? 1 : 0) + ((pMem->flags&MEM_Static) ? 1 : 0) ); assert( (pMem->flags&MEM_RowSet)==0 ); /* If the preserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); if( n<32 ) n = 32; if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){ if( preserve && pMem->z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); preserve = 0; }else{ |
︙ | ︙ |
Changes to test/fts3defer.test.
︙ | ︙ | |||
485 486 487 488 489 490 491 492 493 | INSERT INTO x2 VALUES('a b c d e f g h i j k l m n o p q r s t u v w x y m'); COMMIT; } do_execsql_test 4.2 { SELECT * FROM x2 WHERE x2 MATCH 'a b c d e f g h i j k l m n o p q r s'; } {{a b c d e f g h i j k l m n o p q r s t u v w x y m}} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | INSERT INTO x2 VALUES('a b c d e f g h i j k l m n o p q r s t u v w x y m'); COMMIT; } do_execsql_test 4.2 { SELECT * FROM x2 WHERE x2 MATCH 'a b c d e f g h i j k l m n o p q r s'; } {{a b c d e f g h i j k l m n o p q r s t u v w x y m}} set tokenizers {1 simple} ifcapable icu { lappend tokenizers 2 {icu en_US} } foreach {tn tokenizer} $tokenizers { do_execsql_test 5.$tn.1 " CREATE VIRTUAL TABLE x3 USING FTS4(a, b, TOKENIZE $tokenizer) " do_execsql_test 5.$tn.2 { BEGIN; INSERT INTO x3 VALUES('b b b b b b b b b b b', 'b b b b b b b b b b b b b'); INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 SELECT * FROM x3; INSERT INTO x3 VALUES('a b c', NULL); INSERT INTO x3 VALUES('a x c', NULL); COMMIT; SELECT * FROM x3 WHERE x3 MATCH 'a b'; } {{a b c} {}} do_execsql_test 5.$tn.3 { DROP TABLE x3 } } finish_test |
Changes to test/fts4merge3.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/fts3_common.tcl source $testdir/lock_common.tcl source $testdir/bc_common.tcl set ::testprefix fts4merge3 if {"" == [bc_find_binaries backcompat.test]} { finish_test return } db close do_all_bc_test { sql2 { PRAGMA page_size = 512 } if { 0==[catch { sql2 { CREATE VIRTUAL TABLE x USING fts4 } } ] } { # Build a large database. set msg "this takes around 12 seconds" do_test "1.1 ($msg)" { fts3_build_db_2 20000 } {} # Run some queries on it, using the old and new versions. do_test 1.2 { sql1 "SELECT docid FROM t2 WHERE t2 MATCH 'abc'" } {1485} do_test 1.3 { sql2 "SELECT docid FROM t2 WHERE t2 MATCH 'abc'" } {1485} | > > > > > | > > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/fts3_common.tcl source $testdir/lock_common.tcl source $testdir/bc_common.tcl set ::testprefix fts4merge3 ifcapable !fts3 { finish_test return } if {"" == [bc_find_binaries backcompat.test]} { finish_test return } db close do_all_bc_test { sql2 { PRAGMA page_size = 512 } if { 0==[catch { sql2 { CREATE VIRTUAL TABLE x USING fts4 } } ] } { # Build a large database. set msg "this takes around 12 seconds" do_test "1.1 ($msg)" { fts3_build_db_2 20000 } {} # Run some queries on it, using the old and new versions. do_test 1.2 { sql1 "SELECT docid FROM t2 WHERE t2 MATCH 'abc'" } {1485} do_test 1.3 { sql2 "SELECT docid FROM t2 WHERE t2 MATCH 'abc'" } {1485} do_test 1.4 { set x [sql2 "PRAGMA page_count"] expr {$x>=1284 && $x<=1286} } {1} do_test 1.5 { sql2 { SELECT level, count(*) FROM t2_segdir GROUP BY level ORDER BY 1 } } [list 0 15 1 1 2 14 3 4] # Run some incr-merge operations on the db. for {set i 0} {$i<10} {incr i} { do_test 1.6.$i.1 { sql1 { INSERT INTO t2(t2) VALUES('merge=2,2') } } {} |
︙ | ︙ |
Changes to test/quota2.test.
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | do_test quota2-1.1 { set ::h1 [sqlite3_quota_fopen quota2a/xyz.txt w+b] sqlite3_quota_fwrite $::h1 1 7000 $bigtext } {4000} do_test quota2-1.2 { set ::quota } {PWD/quota2a/xyz.txt 4000 7000} do_test quota2-1.3 { sqlite3_quota_rewind $::h1 set ::x [sqlite3_quota_fread $::h1 1001 7] string length $::x } {3003} do_test quota2-1.4 { string match $::x [string range $::bigtext 0 3002] | > > > > > > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | do_test quota2-1.1 { set ::h1 [sqlite3_quota_fopen quota2a/xyz.txt w+b] sqlite3_quota_fwrite $::h1 1 7000 $bigtext } {4000} do_test quota2-1.2 { set ::quota } {PWD/quota2a/xyz.txt 4000 7000} do_test quota2-1.2.1 { sqlite3_quota_file_size $::h1 } {4000} do_test quota2-1.2.2 { sqlite3_quota_fflush $::h1 1 sqlite3_quota_file_truesize $::h1 } {4000} do_test quota2-1.3 { sqlite3_quota_rewind $::h1 set ::x [sqlite3_quota_fread $::h1 1001 7] string length $::x } {3003} do_test quota2-1.4 { string match $::x [string range $::bigtext 0 3002] |
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 | sqlite3_quota_rewind $::h1 sqlite3_quota_ftell $::h1 } {0} do_test quota2-1.11 { standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 1 0}}} do_test quota2-1.12 { sqlite3_quota_fclose $::h1 standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 0 0}}} | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | sqlite3_quota_rewind $::h1 sqlite3_quota_ftell $::h1 } {0} do_test quota2-1.11 { standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 1 0}}} do_test quota2-1.12 { sqlite3_quota_ftruncate $::h1 3500 sqlite3_quota_file_size $::h1 } {3500} do_test quota2-1.13 { sqlite3_quota_file_truesize $::h1 } {3500} do_test quota2-1.14 { standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 3500 {PWD/quota2a/xyz.txt 3500 1 0}}} do_test quota2-1.15 { sqlite3_quota_fseek $::h1 0 SEEK_END sqlite3_quota_ftell $::h1 } {3500} do_test quota2-1.16 { sqlite3_quota_fwrite $::h1 1 7000 $bigtext } {500} do_test quota2-1.17 { sqlite3_quota_ftell $::h1 } {4000} do_test quota2-1.18 { sqlite3_quota_file_size $::h1 } {4000} do_test quota2-1.19 { sqlite3_quota_fflush $::h1 1 sqlite3_quota_file_truesize $::h1 } {4000} do_test quota2-1.20 { sqlite3_quota_fclose $::h1 standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 4000 {PWD/quota2a/xyz.txt 4000 0 0}}} do_test quota2-1.21 { sqlite3_quota_remove quota2a/xyz.txt standard_path [sqlite3_quota_dump] } {{*/quota2b/* 5000 0} {*/quota2a/* 4000 0}} set quota {} do_test quota2-2.1 { set ::h1 [sqlite3_quota_fopen quota2c/xyz.txt w+b] sqlite3_quota_fwrite $::h1 1 7000 $bigtext } {7000} |
︙ | ︙ |
Added test/savepoint7.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | # 2012 March 31 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Focus on the interaction between RELEASE and ROLLBACK TO with # pending query aborts. See ticket [27ca74af3c083f787a1c44b11fbb7c53bdbbcf1e]. # set testdir [file dirname $argv0] source $testdir/tester.tcl # The RELEASE of an inner savepoint should not effect pending queries. # do_test savepoint7-1.1 { db eval { CREATE TABLE t1(a,b,c); CREATE TABLE t2(x,y,z); INSERT INTO t1 VALUES(1,2,3); INSERT INTO t1 VALUES(4,5,6); INSERT INTO t1 VALUES(7,8,9); SAVEPOINT x1; } db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2; RELEASE x1} } {1 2 3 4 5 6 7 8 9} do_test savepoint7-1.2 { db eval {DELETE FROM t2;} db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2} } {1 2 3 4 5 6 7 8 9} do_test savepoint7-1.3 { db eval {DELETE FROM t2; BEGIN;} db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); RELEASE x2; } } db eval {SELECT * FROM t2; ROLLBACK;} } {1 2 3 4 5 6 7 8 9} # However, a ROLLBACK of an inner savepoint will abort all queries, including # queries in outer contexts. # do_test savepoint7-2.1 { db eval {DELETE FROM t2; SAVEPOINT x1;} set rc [catch { db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); ROLLBACK TO x2; } } } msg] db eval {RELEASE x1} list $rc $msg [db eval {SELECT * FROM t2}] } {1 {callback requested query abort} {}} do_test savepoint7-2.2 { db eval {DELETE FROM t2;} set rc [catch { db eval {SELECT * FROM t1} { db eval { SAVEPOINT x2; INSERT INTO t2 VALUES($a,$b,$c); ROLLBACK TO x2; } } } msg] list $rc $msg [db eval {SELECT * FROM t2}] } {1 {callback requested query abort} {}} finish_test |
Changes to test/subquery.test.
︙ | ︙ | |||
326 327 328 329 330 331 332 333 334 335 336 337 338 339 | } } {1 one 2 two} do_test subquery-3.3.5 { execsql { SELECT a, (SELECT count(*) FROM t2 WHERE a=c) FROM t1; } } {1 1 2 1} #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite3_reset(). # # One problem was that VDBE memory cells were not being initialised | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | } } {1 one 2 two} do_test subquery-3.3.5 { execsql { SELECT a, (SELECT count(*) FROM t2 WHERE a=c) FROM t1; } } {1 1 2 1} # The following tests check for aggregate subqueries in an aggregate # query. # do_test subquery-3.4.1 { execsql { CREATE TABLE t34(x,y); INSERT INTO t34 VALUES(106,4), (107,3), (106,5), (107,5); SELECT a.x, avg(a.y) FROM t34 AS a GROUP BY a.x HAVING NOT EXISTS( SELECT b.x, avg(b.y) FROM t34 AS b GROUP BY b.x HAVING avg(a.y) > avg(b.y)); } } {107 4.0} do_test subquery-3.4.2 { execsql { SELECT a.x, avg(a.y) AS avg1 FROM t34 AS a GROUP BY a.x HAVING NOT EXISTS( SELECT b.x, avg(b.y) AS avg2 FROM t34 AS b GROUP BY b.x HAVING avg1 > avg2); } } {107 4.0} do_test subquery-3.4.3 { execsql { SELECT a.x, avg(a.y), NOT EXISTS ( SELECT b.x, avg(b.y) FROM t34 AS b GROUP BY b.x HAVING avg(a.y) > avg(b.y)), EXISTS ( SELECT c.x, avg(c.y) FROM t34 AS c GROUP BY c.x HAVING avg(a.y) > avg(c.y)) FROM t34 AS a GROUP BY a.x ORDER BY a.x; } } {106 4.5 0 1 107 4.0 1 0} #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite3_reset(). # # One problem was that VDBE memory cells were not being initialised |
︙ | ︙ |
Changes to tool/build-shell.sh.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # ~/sqlite/bld. There should be an appropriate Makefile in the current # directory as well. # make sqlite3.c gcc -o sqlite3 -g -Os -I. \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_ENABLE_VFSTRACE \ | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # ~/sqlite/bld. There should be an appropriate Makefile in the current # directory as well. # make sqlite3.c gcc -o sqlite3 -g -Os -I. \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_ENABLE_VFSTRACE \ -DSQLITE_ENABLE_STAT3 \ -DSQLITE_ENABLE_FTS4 \ -DSQLITE_ENABLE_RTREE \ -DHAVE_READLINE \ -DHAVE_USLEEP=1 \ ../sqlite/src/shell.c ../sqlite/src/test_vfstrace.c \ sqlite3.c -ldl -lreadline -lncurses |
Changes to tool/lemon.c.
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | ** ALGORITHM: ** Merge-sort. */ /* ** Return a pointer to the next structure in the linked list. */ | | | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | ** ALGORITHM: ** Merge-sort. */ /* ** Return a pointer to the next structure in the linked list. */ #define NEXT(A) (*(char**)(((char*)A)+offset)) /* ** Inputs: ** a: A sorted, null-terminated linked list. (May be null). ** b: A sorted, null-terminated linked list. (May be null). ** cmp: A pointer to the comparison function. ** offset: Offset in the structure to the "next" field. |
︙ | ︙ |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
356 357 358 359 360 361 362 | j++; } nKeyword = j; /* Fill in the lengths of strings and hashes for all entries. */ for(i=0; i<nKeyword; i++){ Keyword *p = &aKeywordTable[i]; | | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | j++; } nKeyword = j; /* Fill in the lengths of strings and hashes for all entries. */ for(i=0; i<nKeyword; i++){ Keyword *p = &aKeywordTable[i]; p->len = (int)strlen(p->zName); assert( p->len<sizeof(p->zOrigName) ); strcpy(p->zOrigName, p->zName); totalLen += p->len; p->hash = (UpperToLower[(int)p->zName[0]]*4) ^ (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len; p->id = i+1; } |
︙ | ︙ |
Changes to tool/showdb.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> static int pagesize = 1024; /* Size of a database page */ static int db = -1; /* File descriptor for reading the DB */ static int mxPage = 0; /* Last page number */ static int perLine = 16; /* HEX elements to print per line */ | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" static int pagesize = 1024; /* Size of a database page */ static int db = -1; /* File descriptor for reading the DB */ static int mxPage = 0; /* Last page number */ static int perLine = 16; /* HEX elements to print per line */ |
︙ | ︙ | |||
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | pgno = 0; }else{ pgno = (int)decodeInt32(&a[0]); } free(a); } } /* ** Print a usage comment */ static void usage(const char *argv0){ fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0); fprintf(stderr, "args:\n" " dbheader Show database header\n" " NNN..MMM Show hex of pages NNN through MMM\n" " NNN..end Show hex of pages NNN through end of file\n" " NNNb Decode btree page NNN\n" " NNNbc Decode btree page NNN and show content\n" " NNNbm Decode btree page NNN and show a layout map\n" " NNNt Decode freelist trunk page NNN\n" " NNNtd Show leaf freelist pages on the decode\n" | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | pgno = 0; }else{ pgno = (int)decodeInt32(&a[0]); } free(a); } } /* ** A short text comment on the use of each page. */ static char **zPageUse; /* ** Add a comment on the use of a page. */ static void page_usage_msg(int pgno, const char *zFormat, ...){ va_list ap; char *zMsg; va_start(ap, zFormat); zMsg = sqlite3_vmprintf(zFormat, ap); va_end(ap); if( pgno<=0 || pgno>mxPage ){ printf("ERROR: page %d out of bounds. Range=1..%d. Msg: %s\n", pgno, mxPage, zMsg); sqlite3_free(zMsg); return; } if( zPageUse[pgno]!=0 ){ printf("ERROR: page %d used multiple times:\n", pgno); printf("ERROR: previous: %s\n", zPageUse[pgno]); printf("ERROR: current: %s\n", zPageUse[pgno]); sqlite3_free(zPageUse[pgno]); } zPageUse[pgno] = zMsg; } /* ** Find overflow pages of a cell and describe their usage. */ static void page_usage_cell( unsigned char cType, /* Page type */ unsigned char *a, /* Cell content */ int pgno, /* page containing the cell */ int cellno /* Index of the cell on the page */ ){ int i; int nDesc = 0; int n = 0; i64 nPayload; i64 rowid; int nLocal; i = 0; if( cType<=5 ){ a += 4; n += 4; } if( cType!=5 ){ i = decodeVarint(a, &nPayload); a += i; n += i; nLocal = localPayload(nPayload, cType); }else{ nPayload = nLocal = 0; } if( cType==5 || cType==13 ){ i = decodeVarint(a, &rowid); a += i; n += i; } if( nLocal<nPayload ){ int ovfl = decodeInt32(a+nLocal); int cnt = 0; while( ovfl && (cnt++)<mxPage ){ page_usage_msg(ovfl, "overflow %d from cell %d of page %d", cnt, cellno, pgno); a = getContent((ovfl-1)*pagesize, 4); ovfl = decodeInt32(a); free(a); } } } /* ** Describe the usages of a b-tree page */ static void page_usage_btree( int pgno, /* Page to describe */ int parent, /* Parent of this page. 0 for root pages */ int idx, /* Which child of the parent */ const char *zName /* Name of the table */ ){ unsigned char *a; const char *zType = "corrupt node"; int nCell; int i; int hdr = pgno==1 ? 100 : 0; if( pgno<=0 || pgno>mxPage ) return; a = getContent((pgno-1)*pagesize, pagesize); switch( a[hdr] ){ case 2: zType = "interior node of index"; break; case 5: zType = "interior node of table"; break; case 10: zType = "leaf of index"; break; case 13: zType = "leaf of table"; break; } if( parent ){ page_usage_msg(pgno, "%s [%s], child %d of page %d", zType, zName, idx, parent); }else{ page_usage_msg(pgno, "root %s [%s]", zType, zName); } nCell = a[hdr+3]*256 + a[hdr+4]; if( a[hdr]==2 || a[hdr]==5 ){ int cellstart = hdr+12; unsigned int child; for(i=0; i<nCell; i++){ int ofst; ofst = cellstart + i*2; ofst = a[ofst]*256 + a[ofst+1]; child = decodeInt32(a+ofst); page_usage_btree(child, pgno, i, zName); } child = decodeInt32(a+cellstart-4); page_usage_btree(child, pgno, i, zName); } if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){ int cellstart = hdr + 8 + 4*(a[hdr]<=5); for(i=0; i<nCell; i++){ int ofst; ofst = cellstart + i*2; ofst = a[ofst]*256 + a[ofst+1]; page_usage_cell(a[hdr], a+ofst, pgno, i); } } free(a); } /* ** Determine page usage by the freelist */ static void page_usage_freelist(int pgno){ unsigned char *a; int cnt = 0; int i; int n; int iNext; int parent = 1; while( pgno>0 && pgno<=mxPage && (cnt++)<mxPage ){ page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent); a = getContent((pgno-1)*pagesize, pagesize); iNext = decodeInt32(a); n = decodeInt32(a+4); for(i=0; i<n; i++){ int child = decodeInt32(a + (i*4+8)); page_usage_msg(child, "freelist leaf, child %d of trunk page %d", i, pgno); } free(a); parent = pgno; pgno = iNext; } } /* ** Try to figure out how every page in the database file is being used. */ static void page_usage_report(const char *zDbName){ int i; int rc; sqlite3 *db; sqlite3_stmt *pStmt; unsigned char *a; /* Avoid the pathological case */ if( mxPage<1 ){ printf("empty database\n"); return; } /* Open the database file */ rc = sqlite3_open(zDbName, &db); if( rc ){ printf("cannot open database: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); return; } /* Set up global variables zPageUse[] and mxPage to record page ** usages */ zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(mxPage+1) ); if( zPageUse==0 ) out_of_memory(); memset(zPageUse, 0, sizeof(zPageUse[0])*(mxPage+1)); /* Discover the usage of each page */ a = getContent(0, 100); page_usage_freelist(decodeInt32(a+32)); free(a); page_usage_btree(1, 0, 0, "sqlite_master"); rc = sqlite3_prepare_v2(db, "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage", -1, &pStmt, 0); if( rc==SQLITE_OK ){ while( sqlite3_step(pStmt)==SQLITE_ROW ){ int pgno = sqlite3_column_int(pStmt, 2); page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1)); } }else{ printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db)); } sqlite3_finalize(pStmt); sqlite3_close(db); /* Print the report and free memory used */ for(i=1; i<=mxPage; i++){ printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???"); sqlite3_free(zPageUse[i]); } sqlite3_free(zPageUse); zPageUse = 0; } /* ** Print a usage comment */ static void usage(const char *argv0){ fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0); fprintf(stderr, "args:\n" " dbheader Show database header\n" " pgidx Index of how each page is used\n" " NNN..MMM Show hex of pages NNN through MMM\n" " NNN..end Show hex of pages NNN through end of file\n" " NNNb Decode btree page NNN\n" " NNNbc Decode btree page NNN and show content\n" " NNNbm Decode btree page NNN and show a layout map\n" " NNNt Decode freelist trunk page NNN\n" " NNNtd Show leaf freelist pages on the decode\n" |
︙ | ︙ | |||
498 499 500 501 502 503 504 505 506 507 508 509 510 511 | int i; for(i=2; i<argc; i++){ int iStart, iEnd; char *zLeft; if( strcmp(argv[i], "dbheader")==0 ){ print_db_header(); continue; } if( !isdigit(argv[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); continue; } iStart = strtol(argv[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ | > > > > | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 | int i; for(i=2; i<argc; i++){ int iStart, iEnd; char *zLeft; if( strcmp(argv[i], "dbheader")==0 ){ print_db_header(); continue; } if( strcmp(argv[i], "pgidx")==0 ){ page_usage_report(argv[1]); continue; } if( !isdigit(argv[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); continue; } iStart = strtol(argv[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ |
︙ | ︙ |
Changes to tool/spaceanal.tcl.
︙ | ︙ | |||
45 46 47 48 49 50 51 | } # Compute the total file size assuming test_multiplexor is being used. # Assume that SQLITE_ENABLE_8_3_NAMES might be enabled # set extension [file extension $file_to_analyze] set pattern $file_to_analyze | | < | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | } # Compute the total file size assuming test_multiplexor is being used. # Assume that SQLITE_ENABLE_8_3_NAMES might be enabled # set extension [file extension $file_to_analyze] set pattern $file_to_analyze append pattern {[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] set extension {} } if {[string length $extension]>=2 && [string length $extension]<=4} { set pattern [file rootname $file_to_analyze] append pattern {.[0-3][0-9][0-9]} foreach f [glob -nocomplain $pattern] { incr true_file_size [file size $f] } } # Open the database # |
︙ | ︙ |
Changes to tool/warnings-clang.sh.
1 2 3 4 5 6 7 8 9 10 11 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # rm -f sqlite3.c make sqlite3.c echo '************* FTS4 and RTREE ****************' scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:' echo '********** ENABLE_STAT3. THREADSAFE=0 *******' | | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #/bin/sh # # Run this script in a directory with a working makefile to check for # compiler warnings in SQLite. # rm -f sqlite3.c make sqlite3.c echo '************* FTS4 and RTREE ****************' scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ -DSQLITE_DEBUG sqlite3.c 2>&1 | grep -v 'ANALYZE:' echo '********** ENABLE_STAT3. THREADSAFE=0 *******' scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \ -DSQLITE_DEBUG \ sqlite3.c ../sqlite/src/shell.c -ldl 2>&1 | grep -v 'ANALYZE:' |