Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Pull in all the latest changes from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sessions |
Files: | files | file ages | folders |
SHA1: |
af3ca4c6e557e6bc92584586b5a97d9b |
User & Date: | drh 2013-07-09 13:05:49.248 |
Context
2013-07-11
| ||
12:19 | Rename the SQLITE_DeferForeignKeys macro to shorter SQLITE_DeferFKs. Move the "defer_foreign_keys" pragma into the flagPragma() routine. (check-in: 3a2ab74c85 user: drh tags: sessions) | |
2013-07-09
| ||
13:05 | Pull in all the latest changes from trunk. (check-in: af3ca4c6e5 user: drh tags: sessions) | |
12:36 | Modify several extensions to use the new exported function naming. Fix some shared library compilation issues. (check-in: 1e39f85077 user: drh tags: trunk) | |
2013-07-04
| ||
15:22 | Fix a bug preventing some FK constraint checking from being deferred until the end of changeset application. (check-in: 1452defb8c user: dan tags: sessions) | |
Changes
Changes to ext/fts1/fts1.c.
︙ | ︙ | |||
3331 3332 3333 3334 3335 3336 3337 | int sqlite3Fts1Init(sqlite3 *db){ sqlite3_overload_function(db, "snippet", -1); sqlite3_overload_function(db, "offsets", -1); return sqlite3_create_module(db, "fts1", &fulltextModule, 0); } #if !SQLITE_CORE | > > > | | | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 | int sqlite3Fts1Init(sqlite3 *db){ sqlite3_overload_function(db, "snippet", -1); sqlite3_overload_function(db, "offsets", -1); return sqlite3_create_module(db, "fts1", &fulltextModule, 0); } #if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_fts1_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3Fts1Init(db); } #endif #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */ |
Changes to ext/fts1/fulltext.c.
︙ | ︙ | |||
848 849 850 851 852 853 854 | /* Current interface: ** argv[0] - module name ** argv[1] - database name ** argv[2] - table name ** argv[3] - tokenizer name (optional, a sensible default is provided) ** argv[4..] - passed to tokenizer (optional based on tokenizer) **/ | | > > > > | > > | 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 | /* Current interface: ** argv[0] - module name ** argv[1] - database name ** argv[2] - table name ** argv[3] - tokenizer name (optional, a sensible default is provided) ** argv[4..] - passed to tokenizer (optional based on tokenizer) **/ static int fulltextConnect( sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **pzErr ){ int rc; fulltext_vtab *v; sqlite3_tokenizer_module *m = NULL; assert( argc>=3 ); v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab)); /* sqlite will initialize v->base */ |
︙ | ︙ | |||
894 895 896 897 898 899 900 | memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); *ppVTab = &v->base; return SQLITE_OK; } | | > > > > | > > | 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 | memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); *ppVTab = &v->base; return SQLITE_OK; } static int fulltextCreate( sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **pzErr ){ int rc; assert( argc>=3 ); /* The %_content table holds the text of each full-text item, with ** the rowid used as the docid. ** ** The %_term table maps each term to a document list blob |
︙ | ︙ | |||
930 931 932 933 934 935 936 | */ rc = sql_exec(db, argv[2], "create table %_content(content text);" "create table %_term(term text, first integer, doclist blob);" "create index %_index on %_term(term, first)"); if( rc!=SQLITE_OK ) return rc; | | | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 | */ rc = sql_exec(db, argv[2], "create table %_content(content text);" "create table %_term(term text, first integer, doclist blob);" "create index %_index on %_term(term, first)"); if( rc!=SQLITE_OK ) return rc; return fulltextConnect(db, pAux, argc, argv, ppVTab, pzErr); } /* Decide how to handle an SQL query. * At the moment, MATCH queries can include implicit boolean ANDs; we * haven't implemented phrase searches or OR yet. */ static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ int i; |
︙ | ︙ | |||
1484 1485 1486 1487 1488 1489 1490 | }; int fulltext_init(sqlite3 *db){ return sqlite3_create_module(db, "fulltext", &fulltextModule, 0); } #if !SQLITE_CORE | > > > | | | 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 | }; int fulltext_init(sqlite3 *db){ return sqlite3_create_module(db, "fulltext", &fulltextModule, 0); } #if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_fulltext_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ SQLITE_EXTENSION_INIT2(pApi) return fulltext_init(db); } #endif |
Changes to ext/fts2/fts2.c.
︙ | ︙ | |||
6840 6841 6842 6843 6844 6845 6846 | sqlite3Fts2HashClear(pHash); sqlite3_free(pHash); } return rc; } #if !SQLITE_CORE | > > > | | 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 | sqlite3Fts2HashClear(pHash); sqlite3_free(pHash); } return rc; } #if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_fts2_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3Fts2Init(db); } |
︙ | ︙ |
Changes to ext/fts2/fts2_hash.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include <assert.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "fts2_hash.h" /* ** Malloc and Free functions */ static void *fts2HashMalloc(int n){ void *p = sqlite3_malloc(n); | > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include <assert.h> #include <stdlib.h> #include <string.h> #include "sqlite3.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT3 #include "fts2_hash.h" /* ** Malloc and Free functions */ static void *fts2HashMalloc(int n){ void *p = sqlite3_malloc(n); |
︙ | ︙ |
Changes to ext/fts2/fts2_porter.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "fts2_tokenizer.h" /* ** Class derived from sqlite3_tokenizer */ typedef struct porter_tokenizer { sqlite3_tokenizer base; /* Base class */ | > > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "sqlite3.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT3 #include "fts2_tokenizer.h" /* ** Class derived from sqlite3_tokenizer */ typedef struct porter_tokenizer { sqlite3_tokenizer base; /* Base class */ |
︙ | ︙ |
Changes to ext/fts2/fts2_tokenizer.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include "sqlite3.h" #include "sqlite3ext.h" | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) #include "sqlite3.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT3 #include "fts2_hash.h" #include "fts2_tokenizer.h" #include <assert.h> /* ** Implementation of the SQL scalar function for accessing the underlying |
︙ | ︙ |
Changes to ext/fts2/fts2_tokenizer1.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "fts2_tokenizer.h" typedef struct simple_tokenizer { sqlite3_tokenizer base; char delim[128]; /* flag ASCII delimiters */ } simple_tokenizer; | > > > | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "sqlite3.h" #include "sqlite3ext.h" SQLITE_EXTENSION_INIT3 #include "fts2_tokenizer.h" typedef struct simple_tokenizer { sqlite3_tokenizer base; char delim[128]; /* flag ASCII delimiters */ } simple_tokenizer; |
︙ | ︙ |
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 | nDb = (int)strlen(argv[1]) + 1; nName = (int)strlen(argv[2]) + 1; nByte = sizeof(const char *) * (argc-2); aCol = (const char **)sqlite3_malloc(nByte); if( aCol ){ | | | 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 | nDb = (int)strlen(argv[1]) + 1; nName = (int)strlen(argv[2]) + 1; nByte = sizeof(const char *) * (argc-2); aCol = (const char **)sqlite3_malloc(nByte); if( aCol ){ memset((void*)aCol, 0, nByte); azNotindexed = (char **)sqlite3_malloc(nByte); } if( azNotindexed ){ memset(azNotindexed, 0, nByte); } if( !aCol || !azNotindexed ){ rc = SQLITE_NOMEM; |
︙ | ︙ | |||
1342 1343 1344 1345 1346 1347 1348 | p->azColumn[iCol] = zCsr; zCsr += n+1; assert( zCsr <= &((char *)p)[nByte] ); } /* Fill in the abNotindexed array */ for(iCol=0; iCol<nCol; iCol++){ | | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | p->azColumn[iCol] = zCsr; zCsr += n+1; assert( zCsr <= &((char *)p)[nByte] ); } /* Fill in the abNotindexed array */ for(iCol=0; iCol<nCol; iCol++){ int n = (int)strlen(p->azColumn[iCol]); for(i=0; i<nNotindexed; i++){ char *zNot = azNotindexed[i]; if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){ p->abNotindexed[iCol] = 1; sqlite3_free(zNot); azNotindexed[i] = 0; } |
︙ | ︙ | |||
5372 5373 5374 5375 5376 5377 5378 | } #endif #if !SQLITE_CORE /* ** Initialize API pointer table, if required. */ | > > > | | 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 | } #endif #if !SQLITE_CORE /* ** Initialize API pointer table, if required. */ #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_fts3_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3Fts3Init(db); } #endif #endif |
Changes to ext/fts3/fts3Int.h.
︙ | ︙ | |||
28 29 30 31 32 33 34 | #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE # include "sqlite3ext.h" | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #endif #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* If not building as part of the core, include sqlite3ext.h. */ #ifndef SQLITE_CORE # include "sqlite3ext.h" SQLITE_EXTENSION_INIT3 #endif #include "sqlite3.h" #include "fts3_tokenizer.h" #include "fts3_hash.h" /* |
︙ | ︙ |
Changes to ext/icu/icu.c.
︙ | ︙ | |||
484 485 486 487 488 489 490 | ); } return rc; } #if !SQLITE_CORE | > > > | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | ); } return rc; } #if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_icu_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3IcuInit(db); } |
︙ | ︙ |
Changes to ext/misc/ieee754.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** and input of IEEE754 Binary64 floating-point numbers. ** ** ieee754(X) ** ieee754(Y,Z) ** ** In the first form, the value X should be a floating-point number. ** The function will return a string of the form 'ieee754(Y,Z)' where | | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** and input of IEEE754 Binary64 floating-point numbers. ** ** ieee754(X) ** ieee754(Y,Z) ** ** In the first form, the value X should be a floating-point number. ** The function will return a string of the form 'ieee754(Y,Z)' where ** Y and Z are integers such that X==Y*pow(2,Z). ** ** In the second form, Y and Z are integers which are the mantissa and ** base-2 exponent of a new floating point number. The function returns ** a floating-point value equal to Y*pow(2,Z). ** ** Examples: ** ** ieee754(2.0) -> 'ieee754(2,0)' ** ieee754(45.25) -> 'ieee754(181,-2)' ** ieee754(2, 0) -> 2.0 ** ieee754(181, -2) -> 45.25 |
︙ | ︙ |
Changes to ext/misc/nextchar.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 2013-02-28 ** ** 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. ** ****************************************************************************** ** | | | | | | > > > > > > > > > > | 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 | /* ** 2013-02-28 ** ** 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. ** ****************************************************************************** ** ** This file contains code to implement the next_char(A,T,F,W,C) SQL function. ** ** The next_char(A,T,F,W,C) function finds all valid "next" characters for ** string A given the vocabulary in T.F. If the W value exists and is a ** non-empty string, then it is an SQL expression that limits the entries ** in T.F that will be considered. If C exists and is a non-empty string, ** then it is the name of the collating sequence to use for comparison. If ** ** Only the first three arguments are required. If the C parameter is ** omitted or is NULL or is an empty string, then the default collating ** sequence of T.F is used for comparision. If the W parameter is omitted ** or is NULL or is an empty string, then no filtering of the output is ** done. ** ** The T.F column should be indexed using collation C or else this routine ** will be quite slow. ** ** For example, suppose an application has a dictionary like this: ** ** CREATE TABLE dictionary(word TEXT UNIQUE); ** ** Further suppose that for user keypad entry, it is desired to disable ** (gray out) keys that are not valid as the next character. If the |
︙ | ︙ | |||
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | int argc, sqlite3_value **argv ){ nextCharContext c; const unsigned char *zTable = sqlite3_value_text(argv[1]); const unsigned char *zField = sqlite3_value_text(argv[2]); const unsigned char *zWhere; char *zSql; int rc; memset(&c, 0, sizeof(c)); c.db = sqlite3_context_db_handle(context); c.zPrefix = sqlite3_value_text(argv[0]); c.nPrefix = sqlite3_value_bytes(argv[0]); if( zTable==0 || zField==0 || c.zPrefix==0 ) return; | > > > | | | | | > > > > > > | > > > | < < > > > > > > > | | | | | | | < > > > | 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 242 243 244 245 246 247 248 249 | int argc, sqlite3_value **argv ){ nextCharContext c; const unsigned char *zTable = sqlite3_value_text(argv[1]); const unsigned char *zField = sqlite3_value_text(argv[2]); const unsigned char *zWhere; const unsigned char *zCollName; char *zWhereClause = 0; char *zColl = 0; char *zSql; int rc; memset(&c, 0, sizeof(c)); c.db = sqlite3_context_db_handle(context); c.zPrefix = sqlite3_value_text(argv[0]); c.nPrefix = sqlite3_value_bytes(argv[0]); if( zTable==0 || zField==0 || c.zPrefix==0 ) return; if( argc>=4 && (zWhere = sqlite3_value_text(argv[3]))!=0 && zWhere[0]!=0 ){ zWhereClause = sqlite3_mprintf("AND (%s)", zWhere); if( zWhereClause==0 ){ sqlite3_result_error_nomem(context); return; } }else{ zWhereClause = ""; } if( argc>=5 && (zCollName = sqlite3_value_text(argv[4]))!=0 && zCollName[0]!=0 ){ zColl = sqlite3_mprintf("collate \"%w\"", zCollName); if( zColl==0 ){ sqlite3_result_error_nomem(context); if( zWhereClause[0] ) sqlite3_free(zWhereClause); return; } }else{ zColl = ""; } zSql = sqlite3_mprintf( "SELECT \"%w\" FROM \"%w\"" " WHERE \"%w\">=(?1 || ?2) %s" " AND \"%w\"<=(?1 || char(1114111)) %s" /* 1114111 == 0x10ffff */ " %s" " ORDER BY 1 %s ASC LIMIT 1", zField, zTable, zField, zColl, zField, zColl, zWhereClause, zColl ); if( zWhereClause[0] ) sqlite3_free(zWhereClause); if( zColl[0] ) sqlite3_free(zColl); if( zSql==0 ){ sqlite3_result_error_nomem(context); return; } rc = sqlite3_prepare_v2(c.db, zSql, -1, &c.pStmt, 0); sqlite3_free(zSql); |
︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0, nextCharFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } return rc; } | > > > > | 286 287 288 289 290 291 292 293 294 295 296 297 298 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0, nextCharFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 5, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } return rc; } |
Changes to ext/misc/percentile.c.
︙ | ︙ | |||
186 187 188 189 190 191 192 | double ix, vx; p = (Percentile*)sqlite3_aggregate_context(pCtx, 0); if( p==0 ) return; if( p->a==0 ) return; if( p->nUsed ){ qsort(p->a, p->nUsed, sizeof(double), doubleCmp); ix = (p->rPct-1.0)*(p->nUsed-1)*0.01; | | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | double ix, vx; p = (Percentile*)sqlite3_aggregate_context(pCtx, 0); if( p==0 ) return; if( p->a==0 ) return; if( p->nUsed ){ qsort(p->a, p->nUsed, sizeof(double), doubleCmp); ix = (p->rPct-1.0)*(p->nUsed-1)*0.01; i1 = (unsigned)ix; i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; v1 = p->a[i1]; v2 = p->a[i2]; vx = v1 + (v2-v1)*(ix-i1); sqlite3_result_double(pCtx, vx); } sqlite3_free(p->a); |
︙ | ︙ |
Added ext/misc/vtshim.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 97 98 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 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 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 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 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 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 | /* ** 2013-06-12 ** ** 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. ** ************************************************************************* ** ** A shim that sits between the SQLite virtual table interface and ** runtimes with garbage collector based memory management. */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward references */ typedef struct vtshim_aux vtshim_aux; typedef struct vtshim_vtab vtshim_vtab; typedef struct vtshim_cursor vtshim_cursor; /* The vtshim_aux argument is the auxiliary parameter that is passed ** into sqlite3_create_module_v2(). */ struct vtshim_aux { void *pChildAux; /* pAux for child virtual tables */ void (*xChildDestroy)(void*); /* Destructor for pChildAux */ sqlite3_module *pMod; /* Methods for child virtual tables */ sqlite3 *db; /* The database to which we are attached */ char *zName; /* Name of the module */ int bDisposed; /* True if disposed */ vtshim_vtab *pAllVtab; /* List of all vtshim_vtab objects */ sqlite3_module sSelf; /* Methods used by this shim */ }; /* A vtshim virtual table object */ struct vtshim_vtab { sqlite3_vtab base; /* Base class - must be first */ sqlite3_vtab *pChild; /* Child virtual table */ vtshim_aux *pAux; /* Pointer to vtshim_aux object */ vtshim_cursor *pAllCur; /* List of all cursors */ vtshim_vtab **ppPrev; /* Previous on list */ vtshim_vtab *pNext; /* Next on list */ }; /* A vtshim cursor object */ struct vtshim_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3_vtab_cursor *pChild; /* Cursor generated by the managed subclass */ vtshim_cursor **ppPrev; /* Previous on list of all cursors */ vtshim_cursor *pNext; /* Next on list of all cursors */ }; /* Macro used to copy the child vtable error message to outer vtable */ #define VTSHIM_COPY_ERRMSG() \ do { \ sqlite3_free(pVtab->base.zErrMsg); \ pVtab->base.zErrMsg = sqlite3_mprintf("%s", pVtab->pChild->zErrMsg); \ } while (0) /* Methods for the vtshim module */ static int vtshimCreate( sqlite3 *db, void *ppAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr ){ vtshim_aux *pAux = (vtshim_aux*)ppAux; vtshim_vtab *pNew; int rc; assert( db==pAux->db ); if( pAux->bDisposed ){ if( pzErr ){ *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"", pAux->zName); } return SQLITE_ERROR; } pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); rc = pAux->pMod->xCreate(db, pAux->pChildAux, argc, argv, &pNew->pChild, pzErr); if( rc ){ sqlite3_free(pNew); *ppVtab = 0; } pNew->pAux = pAux; pNew->ppPrev = &pAux->pAllVtab; pNew->pNext = pAux->pAllVtab; if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; pAux->pAllVtab = pNew; return rc; } static int vtshimConnect( sqlite3 *db, void *ppAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr ){ vtshim_aux *pAux = (vtshim_aux*)ppAux; vtshim_vtab *pNew; int rc; assert( db==pAux->db ); if( pAux->bDisposed ){ if( pzErr ){ *pzErr = sqlite3_mprintf("virtual table was disposed: \"%s\"", pAux->zName); } return SQLITE_ERROR; } pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); rc = pAux->pMod->xConnect(db, pAux->pChildAux, argc, argv, &pNew->pChild, pzErr); if( rc ){ sqlite3_free(pNew); *ppVtab = 0; } pNew->pAux = pAux; pNew->ppPrev = &pAux->pAllVtab; pNew->pNext = pAux->pAllVtab; if( pAux->pAllVtab ) pAux->pAllVtab->ppPrev = &pNew->pNext; pAux->pAllVtab = pNew; return rc; } static int vtshimBestIndex( sqlite3_vtab *pBase, sqlite3_index_info *pIdxInfo ){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xBestIndex(pVtab->pChild, pIdxInfo); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimDisconnect(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc = SQLITE_OK; if( !pAux->bDisposed ){ rc = pAux->pMod->xDisconnect(pVtab->pChild); } if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; *pVtab->ppPrev = pVtab->pNext; sqlite3_free(pVtab); return rc; } static int vtshimDestroy(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc = SQLITE_OK; if( !pAux->bDisposed ){ rc = pAux->pMod->xDestroy(pVtab->pChild); } if( pVtab->pNext ) pVtab->pNext->ppPrev = pVtab->ppPrev; *pVtab->ppPrev = pVtab->pNext; sqlite3_free(pVtab); return rc; } static int vtshimOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; vtshim_cursor *pCur; int rc; *ppCursor = 0; if( pAux->bDisposed ) return SQLITE_ERROR; pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); rc = pAux->pMod->xOpen(pVtab->pChild, &pCur->pChild); if( rc ){ sqlite3_free(pCur); VTSHIM_COPY_ERRMSG(); return rc; } pCur->pChild->pVtab = pVtab->pChild; *ppCursor = &pCur->base; pCur->ppPrev = &pVtab->pAllCur; if( pVtab->pAllCur ) pVtab->pAllCur->ppPrev = &pCur->pNext; pCur->pNext = pVtab->pAllCur; pVtab->pAllCur = pCur; return SQLITE_OK; } static int vtshimClose(sqlite3_vtab_cursor *pX){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc = SQLITE_OK; if( !pAux->bDisposed ){ rc = pAux->pMod->xClose(pCur->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } } if( pCur->pNext ) pCur->pNext->ppPrev = pCur->ppPrev; *pCur->ppPrev = pCur->pNext; sqlite3_free(pCur); return rc; } static int vtshimFilter( sqlite3_vtab_cursor *pX, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xFilter(pCur->pChild, idxNum, idxStr, argc, argv); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimNext(sqlite3_vtab_cursor *pX){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xNext(pCur->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimEof(sqlite3_vtab_cursor *pX){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return 1; rc = pAux->pMod->xEof(pCur->pChild); VTSHIM_COPY_ERRMSG(); return rc; } static int vtshimColumn(sqlite3_vtab_cursor *pX, sqlite3_context *ctx, int i){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xColumn(pCur->pChild, ctx, i); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimRowid(sqlite3_vtab_cursor *pX, sqlite3_int64 *pRowid){ vtshim_cursor *pCur = (vtshim_cursor*)pX; vtshim_vtab *pVtab = (vtshim_vtab*)pCur->base.pVtab; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xRowid(pCur->pChild, pRowid); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimUpdate( sqlite3_vtab *pBase, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid ){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xUpdate(pVtab->pChild, argc, argv, pRowid); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimBegin(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xBegin(pVtab->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimSync(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xSync(pVtab->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimCommit(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xCommit(pVtab->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimRollback(sqlite3_vtab *pBase){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xRollback(pVtab->pChild); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimFindFunction( sqlite3_vtab *pBase, int nArg, const char *zName, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg ){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return 0; rc = pAux->pMod->xFindFunction(pVtab->pChild, nArg, zName, pxFunc, ppArg); VTSHIM_COPY_ERRMSG(); return rc; } static int vtshimRename(sqlite3_vtab *pBase, const char *zNewName){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xRename(pVtab->pChild, zNewName); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimSavepoint(sqlite3_vtab *pBase, int n){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xSavepoint(pVtab->pChild, n); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimRelease(sqlite3_vtab *pBase, int n){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xRelease(pVtab->pChild, n); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } static int vtshimRollbackTo(sqlite3_vtab *pBase, int n){ vtshim_vtab *pVtab = (vtshim_vtab*)pBase; vtshim_aux *pAux = pVtab->pAux; int rc; if( pAux->bDisposed ) return SQLITE_ERROR; rc = pAux->pMod->xRollbackTo(pVtab->pChild, n); if( rc!=SQLITE_OK ){ VTSHIM_COPY_ERRMSG(); } return rc; } /* The destructor function for a disposible module */ static void vtshimAuxDestructor(void *pXAux){ vtshim_aux *pAux = (vtshim_aux*)pXAux; assert( pAux->pAllVtab==0 ); if( !pAux->bDisposed && pAux->xChildDestroy ){ pAux->xChildDestroy(pAux->pChildAux); } sqlite3_free(pAux->zName); sqlite3_free(pAux->pMod); sqlite3_free(pAux); } static int vtshimCopyModule( const sqlite3_module *pMod, /* Source module to be copied */ sqlite3_module **ppMod /* Destination for copied module */ ){ sqlite3_module *p; if( !pMod || !ppMod ) return SQLITE_ERROR; p = sqlite3_malloc( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM; memcpy(p, pMod, sizeof(*p)); *ppMod = p; return SQLITE_OK; } #ifdef _WIN32 __declspec(dllexport) #endif void *sqlite3_create_disposable_module( sqlite3 *db, /* SQLite connection to register module with */ const char *zName, /* Name of the module */ const sqlite3_module *p, /* Methods for the module */ void *pClientData, /* Client data for xCreate/xConnect */ void(*xDestroy)(void*) /* Module destructor function */ ){ vtshim_aux *pAux; sqlite3_module *pMod; int rc; pAux = sqlite3_malloc( sizeof(*pAux) ); if( pAux==0 ){ if( xDestroy ) xDestroy(pClientData); return 0; } rc = vtshimCopyModule(p, &pMod); if( rc!=SQLITE_OK ){ sqlite3_free(pAux); return 0; } pAux->pChildAux = pClientData; pAux->xChildDestroy = xDestroy; pAux->pMod = pMod; pAux->db = db; pAux->zName = sqlite3_mprintf("%s", zName); pAux->bDisposed = 0; pAux->pAllVtab = 0; pAux->sSelf.iVersion = p->iVersion<=2 ? p->iVersion : 2; pAux->sSelf.xCreate = p->xCreate ? vtshimCreate : 0; pAux->sSelf.xConnect = p->xConnect ? vtshimConnect : 0; pAux->sSelf.xBestIndex = p->xBestIndex ? vtshimBestIndex : 0; pAux->sSelf.xDisconnect = p->xDisconnect ? vtshimDisconnect : 0; pAux->sSelf.xDestroy = p->xDestroy ? vtshimDestroy : 0; pAux->sSelf.xOpen = p->xOpen ? vtshimOpen : 0; pAux->sSelf.xClose = p->xClose ? vtshimClose : 0; pAux->sSelf.xFilter = p->xFilter ? vtshimFilter : 0; pAux->sSelf.xNext = p->xNext ? vtshimNext : 0; pAux->sSelf.xEof = p->xEof ? vtshimEof : 0; pAux->sSelf.xColumn = p->xColumn ? vtshimColumn : 0; pAux->sSelf.xRowid = p->xRowid ? vtshimRowid : 0; pAux->sSelf.xUpdate = p->xUpdate ? vtshimUpdate : 0; pAux->sSelf.xBegin = p->xBegin ? vtshimBegin : 0; pAux->sSelf.xSync = p->xSync ? vtshimSync : 0; pAux->sSelf.xCommit = p->xCommit ? vtshimCommit : 0; pAux->sSelf.xRollback = p->xRollback ? vtshimRollback : 0; pAux->sSelf.xFindFunction = p->xFindFunction ? vtshimFindFunction : 0; pAux->sSelf.xRename = p->xRename ? vtshimRename : 0; if( p->iVersion>=2 ){ pAux->sSelf.xSavepoint = p->xSavepoint ? vtshimSavepoint : 0; pAux->sSelf.xRelease = p->xRelease ? vtshimRelease : 0; pAux->sSelf.xRollbackTo = p->xRollbackTo ? vtshimRollbackTo : 0; }else{ pAux->sSelf.xSavepoint = 0; pAux->sSelf.xRelease = 0; pAux->sSelf.xRollbackTo = 0; } rc = sqlite3_create_module_v2(db, zName, &pAux->sSelf, pAux, vtshimAuxDestructor); return rc==SQLITE_OK ? (void*)pAux : 0; } #ifdef _WIN32 __declspec(dllexport) #endif void sqlite3_dispose_module(void *pX){ vtshim_aux *pAux = (vtshim_aux*)pX; if( !pAux->bDisposed ){ vtshim_vtab *pVtab; vtshim_cursor *pCur; for(pVtab=pAux->pAllVtab; pVtab; pVtab=pVtab->pNext){ for(pCur=pVtab->pAllCur; pCur; pCur=pCur->pNext){ pAux->pMod->xClose(pCur->pChild); } pAux->pMod->xDisconnect(pVtab->pChild); } pAux->bDisposed = 1; if( pAux->xChildDestroy ) pAux->xChildDestroy(pAux->pChildAux); } } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_vtshim_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi); return SQLITE_OK; } |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
3346 3347 3348 3349 3350 3351 3352 | ** the context object when it is no longer required. */ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free ); } #if !SQLITE_CORE | > > > | | 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 | ** the context object when it is no longer required. */ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY, (void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free ); } #if !SQLITE_CORE #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_rtree_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi) return sqlite3RtreeInit(db); } |
︙ | ︙ |
Changes to mkextw.sh.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/sh # # This script is used to compile SQLite extensions into DLLs. # make fts2amal.c PATH=$PATH:/opt/mingw/bin OPTS='-DTHREADSAFE=1 -DBUILD_sqlite=1 -DSQLITE_OS_WIN=1' CC="i386-mingw32msvc-gcc -O2 $OPTS -Itsrc" NM="i386-mingw32msvc-nm" CMD="$CC -c fts2amal.c" echo $CMD $CMD echo 'EXPORTS' >fts2.def | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/bin/sh # # This script is used to compile SQLite extensions into DLLs. # make fts2amal.c PATH=$PATH:/opt/mingw/bin OPTS='-DTHREADSAFE=1 -DBUILD_sqlite=1 -DSQLITE_OS_WIN=1' CC="i386-mingw32msvc-gcc -O2 $OPTS -Itsrc" NM="i386-mingw32msvc-nm" CMD="$CC -c fts2amal.c" echo $CMD $CMD echo 'EXPORTS' >fts2.def echo 'sqlite3_fts2_init' >>fts2.def i386-mingw32msvc-dllwrap \ --def fts2.def -v --export-all \ --driver-name i386-mingw32msvc-gcc \ --dlltool-name i386-mingw32msvc-dlltool \ --as i386-mingw32msvc-as \ --target i386-mingw32 \ -dllname fts2.dll -lmsvcrt fts2amal.o |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 | /* ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() ** at the conclusion of a transaction. */ static void btreeEndTransaction(Btree *p){ BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); #ifndef SQLITE_OMIT_AUTOVACUUM pBt->bDoTruncate = 0; #endif | > | | 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 | /* ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() ** at the conclusion of a transaction. */ static void btreeEndTransaction(Btree *p){ BtShared *pBt = p->pBt; sqlite3 *db = p->db; assert( sqlite3BtreeHoldsMutex(p) ); #ifndef SQLITE_OMIT_AUTOVACUUM pBt->bDoTruncate = 0; #endif if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){ /* If there are other active statements that belong to this database ** handle, downgrade to a read-only transaction. The other statements ** may still be reading from the database. */ downgradeAllSharedCacheTableLocks(p); p->inTrans = TRANS_READ; }else{ /* If the handle had any kind of transaction open, decrement the |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 | case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break; case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; | > | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 | case SQLITE_ERROR: zName = "SQLITE_ERROR"; break; case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break; case SQLITE_PERM: zName = "SQLITE_PERM"; break; case SQLITE_ABORT: zName = "SQLITE_ABORT"; break; case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break; case SQLITE_BUSY: zName = "SQLITE_BUSY"; break; case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break; case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break; case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break; case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break; case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break; case SQLITE_READONLY: zName = "SQLITE_READONLY"; break; case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break; case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break; case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break; |
︙ | ︙ | |||
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 | case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; case SQLITE_ROW: zName = "SQLITE_ROW"; break; case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break; case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break; case SQLITE_NOTICE_RECOVER_ROLLBACK: zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break; case SQLITE_WARNING: zName = "SQLITE_WARNING"; break; case SQLITE_DONE: zName = "SQLITE_DONE"; break; } } if( zName==0 ){ static char zBuf[50]; sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc); zName = zBuf; | > | 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 | case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break; case SQLITE_ROW: zName = "SQLITE_ROW"; break; case SQLITE_NOTICE: zName = "SQLITE_NOTICE"; break; case SQLITE_NOTICE_RECOVER_WAL: zName = "SQLITE_NOTICE_RECOVER_WAL";break; case SQLITE_NOTICE_RECOVER_ROLLBACK: zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break; case SQLITE_WARNING: zName = "SQLITE_WARNING"; break; case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break; case SQLITE_DONE: zName = "SQLITE_DONE"; break; } } if( zName==0 ){ static char zBuf[50]; sqlite3_snprintf(sizeof(zBuf), zBuf, "SQLITE_UNKNOWN(%d)", origRc); zName = zBuf; |
︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 | /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); if( p && p->iPrefEnc==enc && p->nArg==nArg ){ | | | 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 | /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); if( p && p->iPrefEnc==enc && p->nArg==nArg ){ if( db->nVdbeActive ){ sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE_BUSY; }else{ sqlite3ExpirePreparedStatements(db); } |
︙ | ︙ | |||
1994 1995 1996 1997 1998 1999 2000 | /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ | | | 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 | /* Check if this call is removing or replacing an existing collation ** sequence. If so, and there are active VMs, return busy. If there ** are no active VMs, invalidate any pre-compiled statements. */ pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0); if( pColl && pColl->xCmp ){ if( db->nVdbeActive ){ sqlite3Error(db, SQLITE_BUSY, "unable to delete/modify collation sequence due to active statements"); return SQLITE_BUSY; } sqlite3ExpirePreparedStatements(db); /* If collation sequence pColl was created directly by a call to |
︙ | ︙ | |||
2469 2470 2471 2472 2473 2474 2475 | assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; | | > > > | 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 | assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger #if !defined(SQLITE_DEAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX | SQLITE_AutoIndex #endif #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt #endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION | SQLITE_LoadExtension #endif #if SQLITE_DEFAULT_RECURSIVE_TRIGGERS |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 | */ if( pPager->errCode ){ assert( !MEMDB ); pager_reset(pPager); pPager->changeCountDone = pPager->tempFile; pPager->eState = PAGER_OPEN; pPager->errCode = SQLITE_OK; } pPager->journalOff = 0; pPager->journalHdr = 0; pPager->setMaster = 0; } | > | 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 | */ if( pPager->errCode ){ assert( !MEMDB ); pager_reset(pPager); pPager->changeCountDone = pPager->tempFile; pPager->eState = PAGER_OPEN; pPager->errCode = SQLITE_OK; if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0); } pPager->journalOff = 0; pPager->journalHdr = 0; pPager->setMaster = 0; } |
︙ | ︙ | |||
3374 3375 3376 3377 3378 3379 3380 | /* ** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. */ static void pagerFixMaplimit(Pager *pPager){ #if SQLITE_MAX_MMAP_SIZE>0 sqlite3_file *fd = pPager->fd; | | < > | 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 | /* ** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. */ static void pagerFixMaplimit(Pager *pPager){ #if SQLITE_MAX_MMAP_SIZE>0 sqlite3_file *fd = pPager->fd; if( isOpen(fd) && fd->pMethods->iVersion>=3 ){ sqlite3_int64 sz; sz = pPager->szMmap; pPager->bUseFetch = (sz>0); sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz); } #endif } /* ** Change the maximum size of any memory mapping made of the database file. |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
464 465 466 467 468 469 470 | flag_rtz = flag_altform2; } if( xtype==etEXP ){ e2 = 0; }else{ e2 = exp; } | | | | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | flag_rtz = flag_altform2; } if( xtype==etEXP ){ e2 = 0; }else{ e2 = exp; } if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); if( bufpt==0 ){ pAccum->mallocFailed = 1; return; } } zOut = bufpt; nsd = 16 + flag_altform2*10; |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
63 64 65 66 67 68 69 | #if defined(_WIN32) || defined(WIN32) # include <io.h> #define isatty(h) _isatty(h) #define access(f,m) _access((f),(m)) #undef popen #define popen(a,b) _popen((a),(b)) #undef pclose | | | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | #if defined(_WIN32) || defined(WIN32) # include <io.h> #define isatty(h) _isatty(h) #define access(f,m) _access((f),(m)) #undef popen #define popen(a,b) _popen((a),(b)) #undef pclose #define pclose _pclose #else /* Make sure isatty() has a prototype. */ extern int isatty(int); #endif #if defined(_WIN32_WCE) |
︙ | ︙ | |||
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 | /* ** Do C-language style dequoting. ** ** \t -> tab ** \n -> newline ** \r -> carriage return ** \NNN -> ascii character NNN in octal ** \\ -> backslash */ static void resolve_backslashes(char *z){ int i, j; char c; for(i=j=0; (c = z[i])!=0; i++, j++){ if( c=='\\' ){ c = z[++i]; if( c=='n' ){ c = '\n'; }else if( c=='t' ){ c = '\t'; }else if( c=='r' ){ c = '\r'; }else if( c>='0' && c<='7' ){ c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; | > > > | 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | /* ** Do C-language style dequoting. ** ** \t -> tab ** \n -> newline ** \r -> carriage return ** \" -> " ** \NNN -> ascii character NNN in octal ** \\ -> backslash */ static void resolve_backslashes(char *z){ int i, j; char c; for(i=j=0; (c = z[i])!=0; i++, j++){ if( c=='\\' ){ c = z[++i]; if( c=='n' ){ c = '\n'; }else if( c=='t' ){ c = '\t'; }else if( c=='r' ){ c = '\r'; }else if( c=='\\' ){ c = '\\'; }else if( c>='0' && c<='7' ){ c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; |
︙ | ︙ | |||
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 | ** 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 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 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | ** 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++; } /* ** An object used to read a CSV file */ typedef struct CSVReader CSVReader; struct CSVReader { const char *zFile; /* Name of the input file */ FILE *in; /* Read the CSV text from this input stream */ char *z; /* Accumulated text for a field */ int n; /* Number of bytes in z */ int nAlloc; /* Space allocated for z[] */ int nLine; /* Current line number */ int cTerm; /* Character that terminated the most recent field */ int cSeparator; /* The separator character. (Usually ",") */ }; /* Append a single byte to z[] */ static void csv_append_char(CSVReader *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; p->z = sqlite3_realloc(p->z, p->nAlloc); if( p->z==0 ){ fprintf(stderr, "out of memory\n"); exit(1); } } p->z[p->n++] = (char)c; } /* Read a single field of CSV text. Compatible with rfc4180 and extended ** with the option of having a separator other than ",". ** ** + Input comes from p->in. ** + Store results in p->z of length p->n. Space to hold p->z comes ** from sqlite3_malloc(). ** + Use p->cSep as the separator. The default is ",". ** + Keep track of the line number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *csv_read_one_field(CSVReader *p){ int c, pc; int cSep = p->cSeparator; p->n = 0; c = fgetc(p->in); if( c==EOF || seenInterrupt ){ p->cTerm = EOF; return 0; } if( c=='"' ){ int startLine = p->nLine; int cQuote = c; pc = 0; while( 1 ){ c = fgetc(p->in); if( c=='\n' ) p->nLine++; if( c==cQuote ){ if( pc==cQuote ){ pc = 0; continue; } } if( (c==cSep && pc==cQuote) || (c=='\n' && pc==cQuote) || (c=='\n' && pc=='\r' && p->n>2 && p->z[p->n-2]==cQuote) || (c==EOF && pc==cQuote) ){ do{ p->n--; }while( p->z[p->n]!=cQuote ); p->z[p->n] = 0; p->cTerm = c; break; } if( pc==cQuote && c!='\r' ){ fprintf(stderr, "%s:%d: unescaped %c character\n", p->zFile, p->nLine, cQuote); } if( c==EOF ){ fprintf(stderr, "%s:%d: unterminated %c-quoted field\n", p->zFile, startLine, cQuote); p->z[p->n] = 0; p->cTerm = EOF; break; } csv_append_char(p, c); pc = c; } }else{ while( c!=EOF && c!=cSep && c!='\n' ){ csv_append_char(p, c); c = fgetc(p->in); } if( c=='\n' ){ p->nLine++; if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--; } p->z[p->n] = 0; p->cTerm = c; } return p->z; } /* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 on error, 2 to exit, and 0 otherwise. */ |
︙ | ︙ | |||
1667 1668 1669 1670 1671 1672 1673 | */ while( zLine[i] && nArg<ArraySize(azArg) ){ while( IsSpace(zLine[i]) ){ i++; } if( zLine[i]==0 ) break; if( zLine[i]=='\'' || zLine[i]=='"' ){ int delim = zLine[i++]; azArg[nArg++] = &zLine[i]; | | > > > | 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 | */ while( zLine[i] && nArg<ArraySize(azArg) ){ while( IsSpace(zLine[i]) ){ i++; } if( zLine[i]==0 ) break; if( zLine[i]=='\'' || zLine[i]=='"' ){ int delim = zLine[i++]; azArg[nArg++] = &zLine[i]; while( zLine[i] && zLine[i]!=delim ){ if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++; i++; } if( zLine[i]==delim ){ zLine[i++] = 0; } if( delim=='"' ) resolve_backslashes(azArg[nArg-1]); }else{ azArg[nArg++] = &zLine[i]; while( zLine[i] && !IsSpace(zLine[i]) ){ i++; } |
︙ | ︙ | |||
1884 1885 1886 1887 1888 1889 1890 | if( HAS_TIMER ){ fprintf(stderr,"%s",zTimerHelp); } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ char *zTable = azArg[2]; /* Insert data into this table */ | | < < | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | < < < < < < < < < < < | < < < > | > | | > > > | | < < < < < | < < | | | > > > | < | | | < < < < | < < < < < < < < < < | | < | > | < < < | > | | | > | | 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 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 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 | if( HAS_TIMER ){ fprintf(stderr,"%s",zTimerHelp); } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ char *zTable = azArg[2]; /* Insert data into this table */ char *zFile = azArg[1]; /* Name of file to extra content from */ sqlite3_stmt *pStmt = NULL; /* A statement */ int nCol; /* Number of columns in the table */ int nByte; /* Number of bytes in an SQL string */ int i, j; /* Loop counters */ int nSep; /* Number of bytes in p->separator[] */ char *zSql; /* An SQL statement */ CSVReader sCsv; /* Reader context */ int (*xCloser)(FILE*); /* Procedure to close th3 connection */ seenInterrupt = 0; memset(&sCsv, 0, sizeof(sCsv)); open_db(p); nSep = strlen30(p->separator); if( nSep==0 ){ fprintf(stderr, "Error: non-null separator required for import\n"); return 1; } if( nSep>1 ){ fprintf(stderr, "Error: multi-character separators not allowed" " for import\n"); return 1; } sCsv.zFile = zFile; sCsv.nLine = 1; if( sCsv.zFile[0]=='|' ){ sCsv.in = popen(sCsv.zFile+1, "r"); sCsv.zFile = "<pipe>"; xCloser = pclose; }else{ sCsv.in = fopen(sCsv.zFile, "rb"); xCloser = fclose; } if( sCsv.in==0 ){ fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); return 1; } sCsv.cSeparator = p->separator[0]; zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); xCloser(sCsv.in); return 1; } nByte = strlen30(zSql); rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; while( csv_read_one_field(&sCsv) ){ zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z); cSep = ','; if( sCsv.cTerm!=sCsv.cSeparator ) break; } if( cSep=='(' ){ sqlite3_free(zCreate); sqlite3_free(sCsv.z); xCloser(sCsv.in); fprintf(stderr,"%s: empty file\n", sCsv.zFile); return 1; } zCreate = sqlite3_mprintf("%z\n)", zCreate); rc = sqlite3_exec(p->db, zCreate, 0, 0, 0); sqlite3_free(zCreate); if( rc ){ fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, sqlite3_errmsg(db)); sqlite3_free(sCsv.z); xCloser(sCsv.in); return 1; } rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); } sqlite3_free(zSql); if( rc ){ if (pStmt) sqlite3_finalize(pStmt); fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); xCloser(sCsv.in); return 1; } nCol = sqlite3_column_count(pStmt); sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); xCloser(sCsv.in); return 1; } sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable); j = strlen30(zSql); for(i=1; i<nCol; i++){ zSql[j++] = ','; zSql[j++] = '?'; } zSql[j++] = ')'; zSql[j] = 0; rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); if (pStmt) sqlite3_finalize(pStmt); xCloser(sCsv.in); return 1; } do{ int startLine = sCsv.nLine; for(i=0; i<nCol; i++){ char *z = csv_read_one_field(&sCsv); if( z==0 && i==0 ) break; sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT); if( i<nCol-1 && sCsv.cTerm!=sCsv.cSeparator ){ fprintf(stderr, "%s:%d: expected %d columns but found %d - " "filling the rest with NULL\n", sCsv.zFile, startLine, nCol, i+1); i++; while( i<nCol ){ sqlite3_bind_null(pStmt, i); i++; } } } if( sCsv.cTerm==sCsv.cSeparator ){ do{ csv_read_one_field(&sCsv); i++; }while( sCsv.cTerm==sCsv.cSeparator ); fprintf(stderr, "%s:%d: expected %d columns but found %d - " "extras ignored\n", sCsv.zFile, startLine, nCol, i); } if( i>=nCol ){ sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); if( rc!=SQLITE_OK ){ fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCsv.zFile, startLine, sqlite3_errmsg(db)); } } }while( sCsv.cTerm!=EOF ); xCloser(sCsv.in); sqlite3_free(sCsv.z); sqlite3_finalize(pStmt); sqlite3_exec(p->db, "COMMIT", 0, 0, 0); }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); |
︙ | ︙ | |||
2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 | fprintf(stderr,"Error: querying schema information\n"); rc = 1; }else{ rc = 0; } }else /* Undocumented commands for internal testing. Subject to change ** without notice. */ if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ int i, v; for(i=1; i<nArg; i++){ v = booleanValue(azArg[i]); fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); } } if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ int i; sqlite3_int64 v; for(i=1; i<nArg; i++){ v = integerValue(azArg[i]); | > > > | > | 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 | fprintf(stderr,"Error: querying schema information\n"); rc = 1; }else{ rc = 0; } }else #ifdef SQLITE_DEBUG /* Undocumented commands for internal testing. Subject to change ** without notice. */ if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){ if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){ int i, v; for(i=1; i<nArg; i++){ v = booleanValue(azArg[i]); fprintf(p->out, "%s: %d 0x%x\n", azArg[i], v, v); } } if( strncmp(azArg[0]+9, "integer", n-9)==0 ){ int i; sqlite3_int64 v; for(i=1; i<nArg; i++){ char zBuf[200]; v = integerValue(azArg[i]); sqlite3_snprintf(sizeof(zBuf), zBuf, "%s: %lld 0x%llx\n", azArg[i], v, v); fprintf(p->out, "%s", zBuf); } } }else #endif if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sqlite3_snprintf(sizeof(p->separator), p->separator, "%.*s", (int)sizeof(p->separator)-1, azArg[1]); }else if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
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 | #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. | > > | 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 | #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) #define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8)) #define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8)) #define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8)) #define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8)) #define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8)) #define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8)) #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) #define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) #define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. |
︙ | ︙ |
Changes to src/sqlite3ext.h.
︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; #else /* This case when the file is being statically linked into the ** application */ # define SQLITE_EXTENSION_INIT1 /*no-op*/ # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ #endif #endif /* _SQLITE3EXT_H_ */ | > > > | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | #endif /* SQLITE_CORE */ #ifndef SQLITE_CORE /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; # define SQLITE_EXTENSION_INIT3 \ extern const sqlite3_api_routines *sqlite3_api; #else /* This case when the file is being statically linked into the ** application */ # define SQLITE_EXTENSION_INIT1 /*no-op*/ # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ # define SQLITE_EXTENSION_INIT3 /*no-op*/ #endif #endif /* _SQLITE3EXT_H_ */ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
894 895 896 897 898 899 900 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; | | | > | | 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ int nVdbeWrite; /* Number of active VDBEs that read and write */ int nVdbeExec; /* Number of nested calls to VdbeExec() */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ void *pCommitArg; /* Argument to xCommitCallback() */ |
︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 | #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) | > | 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 | #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
5955 5956 5957 5958 5959 5960 5961 | const char *zOpt; int onoff; int mask = 0; static const struct { const char *zOptName; int mask; } aOpt[] = { | | > | | | | | | | | > > > > | | 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 | const char *zOpt; int onoff; int mask = 0; static const struct { const char *zOptName; int mask; } aOpt[] = { { "all", SQLITE_AllOpts }, { "none", 0 }, { "query-flattener", SQLITE_QueryFlattener }, { "column-cache", SQLITE_ColumnCache }, { "groupby-order", SQLITE_GroupByOrder }, { "factor-constants", SQLITE_FactorOutConst }, { "real-as-int", SQLITE_IdxRealAsInt }, { "distinct-opt", SQLITE_DistinctOpt }, { "cover-idx-scan", SQLITE_CoverIdxScan }, { "order-by-idx-join", SQLITE_OrderByIdxJoin }, { "transitive", SQLITE_Transitive }, { "subquery-coroutine", SQLITE_SubqCoroutine }, { "omit-noop-join", SQLITE_OmitNoopJoin }, { "stat3", SQLITE_Stat3 }, }; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR; zOpt = Tcl_GetString(objv[2]); for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ if( strcmp(zOpt, aOpt[i].zOptName)==0 ){ mask = aOpt[i].mask; break; } } if( onoff ) mask = ~mask; if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){ Tcl_AppendResult(interp, "unknown optimization - should be one of:", (char*)0); for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0); } return TCL_ERROR; } sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask); return TCL_OK; } |
︙ | ︙ |
Changes to src/test_schema.c.
︙ | ︙ | |||
340 341 342 343 344 345 346 | } #else /* ** Extension load function. */ | > > > | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | } #else /* ** Extension load function. */ #ifdef _WIN32 __declspec(dllexport) #endif int sqlite3_schema_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi ){ SQLITE_EXTENSION_INIT2(pApi); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_create_module(db, "schema", &schemaModule, 0); |
︙ | ︙ |
Changes to src/test_vfs.c.
︙ | ︙ | |||
186 187 188 189 190 191 192 193 | static int tvfsShmOpen(sqlite3_file*); static int tvfsShmLock(sqlite3_file*, int , int, int); static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **); static void tvfsShmBarrier(sqlite3_file*); static int tvfsShmUnmap(sqlite3_file*, int); static sqlite3_io_methods tvfs_io_methods = { | > > > | | > > | 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 | static int tvfsShmOpen(sqlite3_file*); static int tvfsShmLock(sqlite3_file*, int , int, int); static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **); static void tvfsShmBarrier(sqlite3_file*); static int tvfsShmUnmap(sqlite3_file*, int); static int tvfsFetch(sqlite3_file*, sqlite3_int64, int, void**); static int tvfsUnfetch(sqlite3_file*, sqlite3_int64, void*); static sqlite3_io_methods tvfs_io_methods = { 3, /* iVersion */ tvfsClose, /* xClose */ tvfsRead, /* xRead */ tvfsWrite, /* xWrite */ tvfsTruncate, /* xTruncate */ tvfsSync, /* xSync */ tvfsFileSize, /* xFileSize */ tvfsLock, /* xLock */ tvfsUnlock, /* xUnlock */ tvfsCheckReservedLock, /* xCheckReservedLock */ tvfsFileControl, /* xFileControl */ tvfsSectorSize, /* xSectorSize */ tvfsDeviceCharacteristics, /* xDeviceCharacteristics */ tvfsShmMap, /* xShmMap */ tvfsShmLock, /* xShmLock */ tvfsShmBarrier, /* xShmBarrier */ tvfsShmUnmap, /* xShmUnmap */ tvfsFetch, tvfsUnfetch }; static int tvfsResultCode(Testvfs *p, int *pRc){ struct errcode { int eCode; const char *zCode; } aCode[] = { |
︙ | ︙ | |||
614 615 616 617 618 619 620 | nByte = sizeof(sqlite3_io_methods); }else{ nByte = offsetof(sqlite3_io_methods, xShmMap); } pMethods = (sqlite3_io_methods *)ckalloc(nByte); memcpy(pMethods, &tvfs_io_methods, nByte); | > > | > | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | nByte = sizeof(sqlite3_io_methods); }else{ nByte = offsetof(sqlite3_io_methods, xShmMap); } pMethods = (sqlite3_io_methods *)ckalloc(nByte); memcpy(pMethods, &tvfs_io_methods, nByte); pMethods->iVersion = pFd->pReal->pMethods->iVersion; if( pMethods->iVersion>pVfs->iVersion ){ pMethods->iVersion = pVfs->iVersion; } if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){ pMethods->xShmUnmap = 0; pMethods->xShmLock = 0; pMethods->xShmBarrier = 0; pMethods->xShmMap = 0; } pFile->pMethods = pMethods; |
︙ | ︙ | |||
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | } ckfree((char *)pBuffer); } pFd->pShm = 0; return rc; } static int testvfs_obj_cmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ | > > > > > > > > > > > > > > > | 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 | } ckfree((char *)pBuffer); } pFd->pShm = 0; return rc; } static int tvfsFetch( sqlite3_file *pFile, sqlite3_int64 iOfst, int iAmt, void **pp ){ TestvfsFd *pFd = tvfsGetFd(pFile); return sqlite3OsFetch(pFd->pReal, iOfst, iAmt, pp); } static int tvfsUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *p){ TestvfsFd *pFd = tvfsGetFd(pFile); return sqlite3OsUnfetch(pFd->pReal, iOfst, p); } static int testvfs_obj_cmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ |
︙ | ︙ | |||
1339 1340 1341 1342 1343 1344 1345 | static int testvfs_cmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static sqlite3_vfs tvfs_vfs = { | | | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | static int testvfs_cmd( ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static sqlite3_vfs tvfs_vfs = { 3, /* iVersion */ 0, /* szOsFile */ 0, /* mxPathname */ 0, /* pNext */ 0, /* zName */ 0, /* pAppData */ tvfsOpen, /* xOpen */ tvfsDelete, /* xDelete */ |
︙ | ︙ | |||
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 | 0, /* xDlClose */ #endif /* SQLITE_OMIT_LOAD_EXTENSION */ tvfsRandomness, /* xRandomness */ tvfsSleep, /* xSleep */ tvfsCurrentTime, /* xCurrentTime */ 0, /* xGetLastError */ 0, /* xCurrentTimeInt64 */ }; Testvfs *p; /* New object */ sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isFullshm = 0; /* True if -fullshm is passed */ int isDefault = 0; /* True if -default is passed */ int szOsFile = 0; /* Value passed to -szosfile */ int mxPathname = -1; /* Value passed to -mxpathname */ | > > > | | 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 | 0, /* xDlClose */ #endif /* SQLITE_OMIT_LOAD_EXTENSION */ tvfsRandomness, /* xRandomness */ tvfsSleep, /* xSleep */ tvfsCurrentTime, /* xCurrentTime */ 0, /* xGetLastError */ 0, /* xCurrentTimeInt64 */ 0, /* xSetSystemCall */ 0, /* xGetSystemCall */ 0, /* xNextSystemCall */ }; Testvfs *p; /* New object */ sqlite3_vfs *pVfs; /* New VFS */ char *zVfs; int nByte; /* Bytes of space to allocate at p */ int i; int isNoshm = 0; /* True if -noshm is passed */ int isFullshm = 0; /* True if -fullshm is passed */ int isDefault = 0; /* True if -default is passed */ int szOsFile = 0; /* Value passed to -szosfile */ int mxPathname = -1; /* Value passed to -mxpathname */ int iVersion = 3; /* Value passed to -iversion */ if( objc<2 || 0!=(objc%2) ) goto bad_args; for(i=2; i<objc; i += 2){ int nSwitch; char *zSwitch; zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
392 393 394 395 396 397 398 | int lastTokenParsed = -1; /* type of the previous token */ u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; | | | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | int lastTokenParsed = -1; /* type of the previous token */ u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; } pParse->rc = SQLITE_OK; pParse->zTail = zSql; i = 0; assert( pzErrMsg!=0 ); pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); return SQLITE_ERROR; } | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | int nRes; /* Bytes of reserved space at the end of each page */ int nDb; /* Number of attached databases */ if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); return SQLITE_ERROR; } if( db->nVdbeActive>1 ){ sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); return SQLITE_ERROR; } /* Save the current value of the database flags so that it can be ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
585 586 587 588 589 590 591 592 593 594 595 596 597 598 | sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK | > | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
︙ | ︙ | |||
2691 2692 2693 2694 2695 2696 2697 2698 2699 | /* Assert that the p1 parameter is valid. Also that if there is no open ** transaction, then there cannot be any savepoints. */ assert( db->pSavepoint==0 || db->autoCommit==0 ); assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); if( p1==SAVEPOINT_BEGIN ){ | > | | 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 | /* Assert that the p1 parameter is valid. Also that if there is no open ** transaction, then there cannot be any savepoints. */ assert( db->pSavepoint==0 || db->autoCommit==0 ); assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK ); assert( db->pSavepoint || db->isTransactionSavepoint==0 ); assert( checkSavepointCount(db) ); assert( p->bIsReader ); if( p1==SAVEPOINT_BEGIN ){ if( db->nVdbeWrite>0 ){ /* A new savepoint cannot be created if there are active write ** statements (i.e. open read/write incremental blob handles). */ sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - " "SQL statements in progress"); rc = SQLITE_BUSY; }else{ |
︙ | ︙ | |||
2751 2752 2753 2754 2755 2756 2757 | pSavepoint = pSavepoint->pNext ){ iSavepoint++; } if( !pSavepoint ){ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); rc = SQLITE_ERROR; | | | 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 | pSavepoint = pSavepoint->pNext ){ iSavepoint++; } if( !pSavepoint ){ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName); rc = SQLITE_ERROR; }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){ /* It is not possible to release (commit) a savepoint if there are ** active write statements. */ sqlite3SetString(&p->zErrMsg, db, "cannot release savepoint - SQL statements in progress" ); rc = SQLITE_BUSY; |
︙ | ︙ | |||
2853 2854 2855 2856 2857 2858 2859 | int turnOnAC; desiredAutoCommit = pOp->p1; iRollback = pOp->p2; turnOnAC = desiredAutoCommit && !db->autoCommit; assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); assert( desiredAutoCommit==1 || iRollback==0 ); | | > | | | 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 | int turnOnAC; desiredAutoCommit = pOp->p1; iRollback = pOp->p2; turnOnAC = desiredAutoCommit && !db->autoCommit; assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); assert( desiredAutoCommit==1 || iRollback==0 ); assert( db->nVdbeActive>0 ); /* At least this one VM is active */ assert( p->bIsReader ); #if 0 if( turnOnAC && iRollback && db->nVdbeActive>1 ){ /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; }else #endif if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){ /* If this instruction implements a COMMIT and other VMs are writing ** return an error indicating that the other VMs must complete first. */ sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; }else if( desiredAutoCommit!=db->autoCommit ){ |
︙ | ︙ | |||
2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 | ** will automatically commit when the VDBE halts. ** ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( pOp->p2 && p->usesStmtJournal | > > | | 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 | ** will automatically commit when the VDBE halts. ** ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { Btree *pBt; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( pOp->p2 && p->usesStmtJournal && (db->autoCommit==0 || db->nVdbeRead>1) ){ assert( sqlite3BtreeIsInTrans(pBt) ); if( p->iStatement==0 ){ assert( db->nStatement>=0 && db->nSavepoint>=0 ); db->nStatement++; p->iStatement = db->nSavepoint + db->nStatement; } |
︙ | ︙ | |||
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 | ** executing this instruction. */ case OP_ReadCookie: { /* out2-prerelease */ int iMeta; int iDb; int iCookie; iDb = pOp->p1; iCookie = pOp->p3; assert( pOp->p3<SQLITE_N_BTREE_META ); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 ); | > | 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 | ** executing this instruction. */ case OP_ReadCookie: { /* out2-prerelease */ int iMeta; int iDb; int iCookie; assert( p->bIsReader ); iDb = pOp->p1; iCookie = pOp->p3; assert( pOp->p3<SQLITE_N_BTREE_META ); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 ); |
︙ | ︙ | |||
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 | ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pIn3 = &aMem[pOp->p3]; sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); | > | 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 | ** A transaction must be started before executing this opcode. */ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2<SQLITE_N_BTREE_META ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pIn3 = &aMem[pOp->p3]; sqlite3VdbeMemIntegerify(pIn3); /* See note about index shifting on OP_ReadCookie */ rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i); |
︙ | ︙ | |||
3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 | int iMeta; int iGen; Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ iGen = iMeta = 0; } | > | 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 | int iMeta; int iGen; Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); assert( p->bIsReader ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ iGen = iMeta = 0; } |
︙ | ︙ | |||
3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 | int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); if( p->expired ){ rc = SQLITE_ABORT; break; } nField = 0; | > > | 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 | int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || p->readOnly==0 ); if( p->expired ){ rc = SQLITE_ABORT; break; } nField = 0; |
︙ | ︙ | |||
4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 | */ case OP_Destroy: { /* out2-prerelease */ int iMoved; int iCnt; Vdbe *pVdbe; int iDb; #ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ | > | > > | | 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 | */ case OP_Destroy: { /* out2-prerelease */ int iMoved; int iCnt; Vdbe *pVdbe; int iDb; assert( p->readOnly==0 ); #ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ iCnt++; } } #else iCnt = db->nVdbeRead; #endif pOut->flags = MEM_Null; if( iCnt>1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ iDb = pOp->p3; |
︙ | ︙ | |||
4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 | ** ** See also: Destroy */ case OP_Clear: { int nChange; nChange = 0; assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); if( pOp->p3 ){ p->nChange += nChange; if( pOp->p3>0 ){ | > | 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 | ** ** See also: Destroy */ case OP_Clear: { int nChange; nChange = 0; assert( p->readOnly==0 ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); if( pOp->p3 ){ p->nChange += nChange; if( pOp->p3>0 ){ |
︙ | ︙ | |||
4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 | int pgno; int flags; Db *pDb; pgno = 0; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ flags = BTREE_INTKEY; }else{ flags = BTREE_BLOBKEY; | > | 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 | int pgno; int flags; Db *pDb; pgno = 0; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); assert( p->readOnly==0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ flags = BTREE_INTKEY; }else{ flags = BTREE_BLOBKEY; |
︙ | ︙ | |||
5031 5032 5033 5034 5035 5036 5037 | case OP_IntegrityCk: { int nRoot; /* Number of tables to check. (Number of root pages.) */ int *aRoot; /* Array of rootpage numbers for tables to be checked */ int j; /* Loop counter */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ | | > | 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 | case OP_IntegrityCk: { int nRoot; /* Number of tables to check. (Number of root pages.) */ int *aRoot; /* Array of rootpage numbers for tables to be checked */ int j; /* Loop counter */ int nErr; /* Number of errors reported */ char *z; /* Text of the error report */ Mem *pnErr; /* Register keeping track of errors remaining */ assert( p->bIsReader ); nRoot = pOp->p2; assert( nRoot>0 ); aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); if( aRoot==0 ) goto no_mem; assert( pOp->p3>0 && pOp->p3<=p->nMem ); pnErr = &aMem[pOp->p3]; assert( (pnErr->flags & MEM_Int)!=0 ); |
︙ | ︙ | |||
5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 | ** mem[P3+2] are initialized to -1. */ case OP_Checkpoint: { int i; /* Loop counter */ int aRes[3]; /* Results */ Mem *pMem; /* Write results here */ aRes[0] = 0; aRes[1] = aRes[2] = -1; assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); | > | 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 | ** mem[P3+2] are initialized to -1. */ case OP_Checkpoint: { int i; /* Loop counter */ int aRes[3]; /* Results */ Mem *pMem; /* Write results here */ assert( p->readOnly==0 ); aRes[0] = 0; aRes[1] = aRes[2] = -1; assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE || pOp->p2==SQLITE_CHECKPOINT_FULL || pOp->p2==SQLITE_CHECKPOINT_RESTART ); rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]); |
︙ | ︙ | |||
5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 | || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY || eNew==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_QUERY ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); eOld = sqlite3PagerGetJournalMode(pPager); if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; | > | 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 | || eNew==PAGER_JOURNALMODE_PERSIST || eNew==PAGER_JOURNALMODE_OFF || eNew==PAGER_JOURNALMODE_MEMORY || eNew==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_QUERY ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); eOld = sqlite3PagerGetJournalMode(pPager); if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; |
︙ | ︙ | |||
5611 5612 5613 5614 5615 5616 5617 | ){ eNew = eOld; } if( (eNew!=eOld) && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) ){ | | | 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 | ){ eNew = eOld; } if( (eNew!=eOld) && (eOld==PAGER_JOURNALMODE_WAL || eNew==PAGER_JOURNALMODE_WAL) ){ if( !db->autoCommit || db->nVdbeRead>1 ){ rc = SQLITE_ERROR; sqlite3SetString(&p->zErrMsg, db, "cannot change %s wal mode from within a transaction", (eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of") ); break; }else{ |
︙ | ︙ | |||
5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 | /* Opcode: Vacuum * * * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. */ case OP_Vacuum: { rc = sqlite3RunVacuum(&p->zErrMsg, db); break; } #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) /* Opcode: IncrVacuum P1 P2 * * * ** ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; } break; | > > | 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 | /* Opcode: Vacuum * * * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. */ case OP_Vacuum: { assert( p->readOnly==0 ); rc = sqlite3RunVacuum(&p->zErrMsg, db); break; } #endif #if !defined(SQLITE_OMIT_AUTOVACUUM) /* Opcode: IncrVacuum P1 P2 * * * ** ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 ); assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ pc = pOp->p2 - 1; rc = SQLITE_OK; } break; |
︙ | ︙ | |||
5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 | */ case OP_VOpen: { VdbeCursor *pCur; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; sqlite3_module *pModule; pCur = 0; pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); rc = pModule->xOpen(pVtab, &pVtabCursor); importVtabErrMsg(p, pVtab); | > | 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 | */ case OP_VOpen: { VdbeCursor *pCur; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; sqlite3_module *pModule; assert( p->bIsReader ); pCur = 0; pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); rc = pModule->xOpen(pVtab, &pVtabCursor); importVtabErrMsg(p, pVtab); |
︙ | ︙ | |||
6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 | sqlite3_vtab *pVtab; Mem *pName; pVtab = pOp->p4.pVtab->pVtab; pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); assert( memIsValid(pName) ); REGISTER_TRACE(pOp->p1, pName); assert( pName->flags & MEM_Str ); testcase( pName->enc==SQLITE_UTF8 ); testcase( pName->enc==SQLITE_UTF16BE ); testcase( pName->enc==SQLITE_UTF16LE ); rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc==SQLITE_OK ){ | > | 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 | sqlite3_vtab *pVtab; Mem *pName; pVtab = pOp->p4.pVtab->pVtab; pName = &aMem[pOp->p1]; assert( pVtab->pModule->xRename ); assert( memIsValid(pName) ); assert( p->readOnly==0 ); REGISTER_TRACE(pOp->p1, pName); assert( pName->flags & MEM_Str ); testcase( pName->enc==SQLITE_UTF8 ); testcase( pName->enc==SQLITE_UTF16BE ); testcase( pName->enc==SQLITE_UTF16LE ); rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8); if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 | sqlite_int64 rowid; Mem **apArg; Mem *pX; assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ u8 vtabOnConflict = db->vtabOnConflict; apArg = p->apArg; | > | 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 | sqlite_int64 rowid; Mem **apArg; Mem *pX; assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback || pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace ); assert( p->readOnly==0 ); pVtab = pOp->p4.pVtab->pVtab; pModule = (sqlite3_module *)pVtab->pModule; nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ u8 vtabOnConflict = db->vtabOnConflict; apArg = p->apArg; |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
333 334 335 336 337 338 339 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft inVtabMethod:2; /* See comments above */ bft changeCntOn:1; /* True to update the change-counter */ bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ | | > | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft inVtabMethod:2; /* See comments above */ bft changeCntOn:1; /* True to update the change-counter */ bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ bft isPrepareV2:1; /* True if prepared with prepare_v2() */ bft doingRerun:1; /* True if rerunning after an auto-reprepare */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[4]; /* Counters used by sqlite3_stmt_status() */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
378 379 380 381 382 383 384 | goto end_of_step; } if( p->pc<0 ){ /* If there are no other statements currently running, then ** reset the interrupt flag. This prevents a call to sqlite3_interrupt ** from interrupting a statement that has not yet started. */ | | | | | > | | | 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 | goto end_of_step; } if( p->pc<0 ){ /* If there are no other statements currently running, then ** reset the interrupt flag. This prevents a call to sqlite3_interrupt ** from interrupting a statement that has not yet started. */ if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; } assert( db->nVdbeWrite>0 || db->autoCommit==0 || (db->nDeferredCons==0 && db->nDeferredImmCons==0) ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); } #endif db->nVdbeActive++; if( p->readOnly==0 ) db->nVdbeWrite++; if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; } #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); }else #endif /* SQLITE_OMIT_EXPLAIN */ { db->nVdbeExec++; rc = sqlite3VdbeExec(p); db->nVdbeExec--; } #ifndef SQLITE_OMIT_TRACE /* Invoke the profile callback if there is one */ if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){ sqlite3_int64 iNow; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
400 401 402 403 404 405 406 407 408 409 410 411 412 | */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; int nMaxArgs = *pMaxFuncArgs; Op *pOp; int *aLabel = p->aLabel; p->readOnly = 1; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; pOp->opflags = sqlite3OpcodeProperty[opcode]; if( opcode==OP_Function || opcode==OP_AggStep ){ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; | > | > > > > > > > > > > > | 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 | */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int i; int nMaxArgs = *pMaxFuncArgs; Op *pOp; int *aLabel = p->aLabel; p->readOnly = 1; p->bIsReader = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; pOp->opflags = sqlite3OpcodeProperty[opcode]; if( opcode==OP_Function || opcode==OP_AggStep ){ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; }else if( opcode==OP_Transaction ){ if( pOp->p2!=0 ) p->readOnly = 0; p->bIsReader = 1; }else if( opcode==OP_AutoCommit || opcode==OP_Savepoint ){ p->bIsReader = 1; }else if( opcode==OP_Vacuum || opcode==OP_JournalMode #ifndef SQLITE_OMIT_WAL || opcode==OP_Checkpoint #endif ){ p->readOnly = 0; p->bIsReader = 1; #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( opcode==OP_VUpdate ){ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; }else if( opcode==OP_VFilter ){ int n; assert( p->nOp - i >= 3 ); assert( pOp[-1].opcode==OP_Integer ); |
︙ | ︙ | |||
433 434 435 436 437 438 439 | if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ assert( -1-pOp->p2<p->nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } } sqlite3DbFree(p->db, p->aLabel); p->aLabel = 0; | < > | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ assert( -1-pOp->p2<p->nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } } sqlite3DbFree(p->db, p->aLabel); p->aLabel = 0; *pMaxFuncArgs = nMaxArgs; assert( p->bIsReader!=0 || p->btreeMask==0 ); } /* ** Return the address of the next instruction to be inserted. */ int sqlite3VdbeCurrentAddr(Vdbe *p){ assert( p->magic==VDBE_MAGIC_INIT ); |
︙ | ︙ | |||
1960 1961 1962 1963 1964 1965 1966 | } #endif return rc; } /* | | > > | | > | 1972 1973 1974 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 | } #endif return rc; } /* ** This routine checks that the sqlite3.nVdbeActive count variable ** matches the number of vdbe's in the list sqlite3.pVdbe that are ** currently active. An assertion fails if the two counts do not match. ** This is an internal self-check only - it is not an essential processing ** step. ** ** This is a no-op if NDEBUG is defined. */ #ifndef NDEBUG static void checkActiveVdbeCnt(sqlite3 *db){ Vdbe *p; int cnt = 0; int nWrite = 0; int nRead = 0; p = db->pVdbe; while( p ){ if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ cnt++; if( p->readOnly==0 ) nWrite++; if( p->bIsReader ) nRead++; } p = p->pNext; } assert( cnt==db->nVdbeActive ); assert( nWrite==db->nVdbeWrite ); assert( nRead==db->nVdbeRead ); } #else #define checkActiveVdbeCnt(x) #endif /* ** If the Vdbe passed as the first argument opened a statement-transaction, |
︙ | ︙ | |||
2121 2122 2123 2124 2125 2126 2127 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK; } checkActiveVdbeCnt(db); | | > | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 | if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag); closeAllCursors(p); if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_OK; } checkActiveVdbeCnt(db); /* No commit or rollback needed if the program never started or if the ** SQL statement does not read or write a database file. */ if( p->pc>=0 && p->bIsReader ){ int mrc; /* Primary error code from p->rc */ int eStatementOp = 0; int isSpecialError; /* Set to true if a 'special' error */ /* Lock all btrees used by the statement */ sqlite3VdbeEnter(p); |
︙ | ︙ | |||
2175 2176 2177 2178 2179 2180 2181 | ** VM, then we do either a commit or rollback of the current transaction. ** ** Note: This block also runs if one of the special errors handled ** above has occurred. */ if( !sqlite3VtabInSync(db) && db->autoCommit | | | 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 | ** VM, then we do either a commit or rollback of the current transaction. ** ** Note: This block also runs if one of the special errors handled ** above has occurred. */ if( !sqlite3VtabInSync(db) && db->autoCommit && db->nVdbeWrite==(p->readOnly==0) ){ if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ sqlite3VdbeLeave(p); return SQLITE_ERROR; |
︙ | ︙ | |||
2258 2259 2260 2261 2262 2263 2264 | /* Release the locks */ sqlite3VdbeLeave(p); } /* We have successfully halted and closed the VM. Record this fact. */ if( p->pc>=0 ){ | | | | < > > | | | 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 | /* Release the locks */ sqlite3VdbeLeave(p); } /* We have successfully halted and closed the VM. Record this fact. */ if( p->pc>=0 ){ db->nVdbeActive--; if( !p->readOnly ) db->nVdbeWrite--; if( p->bIsReader ) db->nVdbeRead--; assert( db->nVdbeActive>=db->nVdbeRead ); assert( db->nVdbeRead>=db->nVdbeWrite ); assert( db->nVdbeWrite>=0 ); } p->magic = VDBE_MAGIC_HALT; checkActiveVdbeCnt(db); if( p->db->mallocFailed ){ p->rc = SQLITE_NOMEM; } /* If the auto-commit flag is set to true, then any locks that were held ** by connection db have now been released. Call sqlite3ConnectionUnlocked() ** to invoke any required unlock-notify callbacks. */ if( db->autoCommit ){ sqlite3ConnectionUnlocked(db); } assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 ); return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK); } /* ** Each VDBE holds the result of the most recent sqlite3_step() call ** in p->rc. This routine sets that result back to SQLITE_OK. |
︙ | ︙ |
Changes to src/vdbetrace.c.
︙ | ︙ | |||
43 44 45 46 47 48 49 | zSql += n; } return nTotal; } /* ** This function returns a pointer to a nul-terminated string in memory | | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | zSql += n; } return nTotal; } /* ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the ** string contains a copy of zRawSql but with host parameters expanded to ** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** ** If the SQLITE_TRACE_SIZE_LIMIT macro is defined to an integer, then ** then long strings and blobs are truncated to that many bytes. This ** can be used to prevent unreasonably large trace strings when dealing ** with large (multi-megabyte) strings and blobs. |
︙ | ︙ | |||
83 84 85 86 87 88 89 | StrAccum out; /* Accumulate the output here */ char zBase[100]; /* Initial working space */ db = p->db; sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); out.db = db; | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | StrAccum out; /* Accumulate the output here */ char zBase[100]; /* Initial working space */ db = p->db; sqlite3StrAccumInit(&out, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); out.db = db; if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; while( *(zRawSql++)!='\n' && *zRawSql ); sqlite3StrAccumAppend(&out, "-- ", 3); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } }else{ |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
2459 2460 2461 2462 2463 2464 2465 | /* If another connection has written to the database file since the ** time the read transaction on this connection was started, then ** the write is disallowed. */ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; | | | 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 | /* If another connection has written to the database file since the ** time the read transaction on this connection was started, then ** the write is disallowed. */ if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; rc = SQLITE_BUSY_SNAPSHOT; } return rc; } /* ** End a write transaction. The commit has already been done. This |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
155 156 157 158 159 160 161 | /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Each instance of this object holds a sequence of WhereLoop objects ** that implement some or all of a query plan. ** | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | /* Forward declaration of methods */ static int whereLoopResize(sqlite3*, WhereLoop*, int); /* ** Each instance of this object holds a sequence of WhereLoop objects ** that implement some or all of a query plan. ** ** Think of each WhereLoop object as a node in a graph with arcs ** showing dependences and costs for travelling between nodes. (That is ** not a completely accurate description because WhereLoop costs are a ** vector, not a scalar, and because dependences are many-to-one, not ** one-to-one as are graph nodes. But it is a useful visualization aid.) ** Then a WherePath object is a path through the graph that visits some ** or all of the WhereLoop objects once. ** |
︙ | ︙ | |||
425 426 427 428 429 430 431 | #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. ** The particular combination of bits in each WhereLoop help to ** determine the algorithm that WhereLoop represents. */ | | | | 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 | #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. ** The particular combination of bits in each WhereLoop help to ** determine the algorithm that WhereLoop represents. */ #define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */ #define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */ #define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */ #define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */ #define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */ #define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */ #define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */ #define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */ #define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */ #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */ #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */ #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ /* Convert a WhereCost value (10 times log2(X)) into its integer value X. ** A rough approximation is used. The value returned is not exact. */ static u64 whereCostToInt(WhereCost x){ u64 n; |
︙ | ︙ | |||
818 819 820 821 822 823 824 | } /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). ** Return NULL if there are no more matching WhereTerms. */ | | | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | } /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). ** Return NULL if there are no more matching WhereTerms. */ static WhereTerm *whereScanNext(WhereScan *pScan){ int iCur; /* The cursor on the LHS of the term */ int iColumn; /* The column on the LHS of the term. -1 for IPK */ Expr *pX; /* An expression being tested */ WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ |
︙ | ︙ | |||
905 906 907 908 909 910 911 | ** form X=Y then this routine might also return terms of the form ** "Y <op> <expr>". The number of levels of transitivity is limited, ** but is enough to handle most commonly occurring SQL statements. ** ** If X is not the INTEGER PRIMARY KEY then X must be compatible with ** index pIdx. */ | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | ** form X=Y then this routine might also return terms of the form ** "Y <op> <expr>". The number of levels of transitivity is limited, ** but is enough to handle most commonly occurring SQL statements. ** ** If X is not the INTEGER PRIMARY KEY then X must be compatible with ** index pIdx. */ static WhereTerm *whereScanInit( WhereScan *pScan, /* The WhereScan object being initialized */ WhereClause *pWC, /* The WHERE clause to be scanned */ int iCur, /* Cursor to scan for */ int iColumn, /* Column to scan for */ u32 opMask, /* Operator(s) to scan for */ Index *pIdx /* Must be compatible with this index */ ){ |
︙ | ︙ | |||
1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 | ** TERM_VNULL tag will suppress the not-null check at the beginning ** of the loop. Without the TERM_VNULL flag, the not-null check at ** the start of the loop will prevent any results from being returned. */ if( pExpr->op==TK_NOTNULL && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; int idxNew; WhereTerm *pNewTerm; pNewExpr = sqlite3PExpr(pParse, TK_GT, | > | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 | ** TERM_VNULL tag will suppress the not-null check at the beginning ** of the loop. Without the TERM_VNULL flag, the not-null check at ** the start of the loop will prevent any results from being returned. */ if( pExpr->op==TK_NOTNULL && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 && OptimizationEnabled(db, SQLITE_Stat3) ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; int idxNew; WhereTerm *pNewTerm; pNewExpr = sqlite3PExpr(pParse, TK_GT, |
︙ | ︙ | |||
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 | int n; /* Column counter */ int i; /* Loop counter */ int mxBitCol; /* Maximum column in pSrc->colUsed */ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); addrInit = sqlite3CodeOnce(pParse); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ nColumn = 0; pTable = pSrc->pTab; pWCEnd = &pWC->a[pWC->nTerm]; pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( (idxCols & cMask)==0 ){ if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return; pLoop->aLTerm[nColumn++] = pTerm; idxCols |= cMask; } } } assert( nColumn>0 ); pLoop->u.btree.nEq = pLoop->nLTerm = nColumn; pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED | > > > > > > > | | 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 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 | int n; /* Column counter */ int i; /* Loop counter */ int mxBitCol; /* Maximum column in pSrc->colUsed */ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ u8 sentWarning = 0; /* True if a warnning has been issued */ /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); addrInit = sqlite3CodeOnce(pParse); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ nColumn = 0; pTable = pSrc->pTab; pWCEnd = &pWC->a[pWC->nTerm]; pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( !sentWarning ){ sqlite3_log(SQLITE_WARNING_AUTOINDEX, "automatic index on %s(%s)", pTable->zName, pTable->aCol[iCol].zName); sentWarning = 1; } if( (idxCols & cMask)==0 ){ if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return; pLoop->aLTerm[nColumn++] = pTerm; idxCols |= cMask; } } } assert( nColumn>0 ); pLoop->u.btree.nEq = pLoop->nLTerm = nColumn; pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED | WHERE_AUTO_INDEX; /* Count the number of additional columns needed to create a ** covering index. A "covering index" is an index that contains all ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used |
︙ | ︙ | |||
2567 2568 2569 2570 2571 2572 2573 | WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE_OK; #ifdef SQLITE_ENABLE_STAT3 | | | 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 | WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE_OK; #ifdef SQLITE_ENABLE_STAT3 if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){ sqlite3_value *pRangeVal; tRowcnt iLower = 0; tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pLower ){ |
︙ | ︙ | |||
3113 3114 3115 3116 3117 3118 3119 | if( pItem->zAlias ){ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); } if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 && ALWAYS(pLoop->u.btree.pIndex!=0) ){ char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); | | | > > | < | < < | 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 | if( pItem->zAlias ){ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); } if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 && ALWAYS(pLoop->u.btree.pIndex!=0) ){ char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); zMsg = sqlite3MAppendf(db, zMsg, ((flags & WHERE_AUTO_INDEX) ? "%s USING AUTOMATIC %sINDEX%.0s%s" : "%s USING %sINDEX %s%s"), zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""), pLoop->u.btree.pIndex->zName, zWhere); sqlite3DbFree(db, zWhere); }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg); if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg); }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ |
︙ | ︙ | |||
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 | /* TK_LT */ OP_SeekLt, /* TK_GE */ OP_SeekGe }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ pX = pStart->pExpr; assert( pX!=0 ); | > | > | | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 | /* TK_LT */ OP_SeekLt, /* TK_GE */ OP_SeekGe }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); VdbeComment((v, "pk")); sqlite3ExprCacheAffinityChange(pParse, r1, 1); sqlite3ReleaseTempReg(pParse, rTemp); disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); } if( pEnd ){ Expr *pX; pX = pEnd->pExpr; assert( pX!=0 ); assert( (pEnd->wtFlags & TERM_VNULL)==0 ); testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ memEndValue = ++pParse->nMem; sqlite3ExprCode(pParse, pX->pRight, memEndValue); if( pX->op==TK_LT || pX->op==TK_GT ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; |
︙ | ︙ | |||
3790 3791 3792 3793 3794 3795 3796 | ** uses an index, and this is either the first OR-connected term ** processed or the index is the same as that used by all previous ** terms, set pCov to the candidate covering index. Otherwise, set ** pCov to NULL to indicate that no candidate covering index will ** be available. */ pSubLoop = pSubWInfo->a[0].pWLoop; | | | 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 | ** uses an index, and this is either the first OR-connected term ** processed or the index is the same as that used by all previous ** terms, set pCov to the candidate covering index. Otherwise, set ** pCov to NULL to indicate that no candidate covering index will ** be available. */ pSubLoop = pSubWInfo->a[0].pWLoop; assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 && (ii==0 || pSubLoop->u.btree.pIndex==pCov) ){ assert( pSubWInfo->a[0].iIdxCur==iCovCur ); pCov = pSubLoop->u.btree.pIndex; }else{ pCov = 0; |
︙ | ︙ | |||
3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; WhereTerm *pAlt; Expr sEq; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; if( pTerm->leftCursor!=iCur ) continue; pE = pTerm->pExpr; assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( (pTerm->prereqRight & newNotReady)!=0 ); pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; testcase( pAlt->eOperator & WO_EQ ); | > | 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 | for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; WhereTerm *pAlt; Expr sEq; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; if( pTerm->leftCursor!=iCur ) continue; if( pLevel->iLeftJoin ) continue; pE = pTerm->pExpr; assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( (pTerm->prereqRight & newNotReady)!=0 ); pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; testcase( pAlt->eOperator & WO_EQ ); |
︙ | ︙ | |||
3972 3973 3974 3975 3976 3977 3978 | p->wsFlags = 0; } /* ** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. */ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){ | | | | 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 | p->wsFlags = 0; } /* ** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. */ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){ if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){ if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){ sqlite3_free(p->u.vtab.idxStr); p->u.vtab.needFree = 0; p->u.vtab.idxStr = 0; }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ sqlite3DbFree(db, p->u.btree.pIndex->zColAff); sqlite3DbFree(db, p->u.btree.pIndex); p->u.btree.pIndex = 0; } } } |
︙ | ︙ | |||
4020 4021 4022 4023 4024 4025 4026 | static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE_NOMEM; whereLoopClearUnion(db, pTo); memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ pFrom->u.vtab.needFree = 0; | | | 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 | static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){ if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE_NOMEM; whereLoopClearUnion(db, pTo); memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ pFrom->u.vtab.needFree = 0; }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){ pFrom->u.btree.pIndex = 0; } return SQLITE_OK; } /* ** Delete a WhereLoop object |
︙ | ︙ | |||
4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 | saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; rLogSize = estLog(whereCost(pProbe->aiRowEst[0])); for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; if( pTerm->prereqRight & pNew->maskSelf ) continue; pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ | > > > > > | 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 | saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; rLogSize = estLog(whereCost(pProbe->aiRowEst[0])); for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; if( pTerm->prereqRight & pNew->maskSelf ) continue; #ifdef SQLITE_ENABLE_STAT3 if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){ continue; /* skip IS NOT NULL constraints on a NOT NULL column */ } #endif pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ |
︙ | ︙ | |||
4332 4333 4334 4335 4336 4337 4338 | /* Adjust nOut and rRun for STAT3 range values */ WhereCost rDiv; whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq, pBtm, pTop, &rDiv); pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10; } #ifdef SQLITE_ENABLE_STAT3 | | > | 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 | /* Adjust nOut and rRun for STAT3 range values */ WhereCost rDiv; whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq, pBtm, pTop, &rDiv); pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10; } #ifdef SQLITE_ENABLE_STAT3 if( pNew->u.btree.nEq==1 && pProbe->nSample && OptimizationEnabled(db, SQLITE_Stat3) ){ tRowcnt nOut = 0; if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ testcase( pTerm->eOperator & WO_EQ ); testcase( pTerm->eOperator & WO_ISNULL ); rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut); }else if( (pTerm->eOperator & WO_IN) && !ExprHasProperty(pTerm->pExpr, EP_xIsSelect) ){ |
︙ | ︙ | |||
4416 4417 4418 4419 4420 4421 4422 | if( x<BMS-1 ) m |= MASKBIT(x); } return m; } /* | | | 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 | if( x<BMS-1 ) m |= MASKBIT(x); } return m; } /* ** Add all WhereLoop objects for a single table of the join where the table ** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be ** a b-tree table, not a virtual table. */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ Bitmask mExtra /* Extra prerequesites for using this table */ ){ |
︙ | ︙ | |||
4492 4493 4494 4495 4496 4497 4498 | if( pTerm->prereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is | | | | > > > | | | 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 | if( pTerm->prereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** approximately 7*N*log2(N) where N is the number of rows in ** the table being indexed. */ pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) ); /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way ** of knowning how selective the index will ultimately be. It would ** not be unreasonable to make this value much larger. */ pNew->nOut = 43; assert( 43==whereCost(20) ); pNew->rRun = whereCostAdd(rLogSize,pNew->nOut); pNew->wsFlags = WHERE_AUTO_INDEX; pNew->prereq = mExtra | pTerm->prereqRight; rc = whereLoopInsert(pBuilder, pNew); } } } /* Loop over all indices |
︙ | ︙ | |||
4877 4878 4879 4880 4881 4882 4883 | whereLoopClear(db, pNew); return rc; } /* ** Examine a WherePath (with the addition of the extra WhereLoop of the 5th ** parameters) to see if it outputs rows in the requested ORDER BY | | > > > > > > > | 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 | whereLoopClear(db, pNew); return rc; } /* ** Examine a WherePath (with the addition of the extra WhereLoop of the 5th ** parameters) to see if it outputs rows in the requested ORDER BY ** (or GROUP BY) without requiring a separate sort operation. Return: ** ** 0: ORDER BY is not satisfied. Sorting required ** 1: ORDER BY is satisfied. Omit sorting ** -1: Unknown at this time ** ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as ** strict. With GROUP BY and DISTINCT the only requirement is that ** equivalent rows appear immediately adjacent to one another. GROUP BY ** and DISTINT do not require rows to appear in any particular order as long ** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT ** the pOrderBy terms can be matched in any order. With ORDER BY, the ** pOrderBy terms must be matched in strict left-to-right order. */ static int wherePathSatisfiesOrderBy( WhereInfo *pWInfo, /* The WHERE clause */ ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ WherePath *pPath, /* The WherePath to check */ u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */ u16 nLoop, /* Number of entries in pPath->aLoop[] */ |
︙ | ︙ | |||
5130 5131 5132 5133 5134 5135 5136 | zName[i] = 0; return zName; } #endif /* | | | 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 | zName[i] = 0; return zName; } #endif /* ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine ** attempts to find the lowest cost path that visits each WhereLoop ** once. This path is then loaded into the pWInfo->a[].pWLoop fields. ** ** Assume that the total number of output rows that will need to be sorted ** will be nRowEst (in the 10*log2 representation). Or, ignore sorting ** costs if nRowEst==0. ** |
︙ | ︙ | |||
5547 5548 5549 5550 5551 5552 5553 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** | | > | 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** ** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause ** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement ** if there is one. If there is no ORDER BY clause or if this routine ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. */ WhereInfo *sqlite3WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ |
︙ | ︙ | |||
5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 | /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); whereClauseInit(&pWInfo->sWC, pWInfo); sqlite3ExprCodeConstants(pParse, pWhere); whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); pWhere = 0; | > | 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 | /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); whereClauseInit(&pWInfo->sWC, pWInfo); sqlite3ExprCodeConstants(pParse, pWhere); whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL); pWhere = 0; |
︙ | ︙ | |||
5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 | if( pWInfo->nLevel>=2 && pResultSet!=0 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy); while( pWInfo->nLevel>=2 ){ pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 && (pLoop->wsFlags & WHERE_ONEROW)==0 ){ break; } if( (tabUsed & pLoop->maskSelf)!=0 ) break; WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId)); pWInfo->nLevel--; nTabList--; } } WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; | > > > > > > > > > > | 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 | if( pWInfo->nLevel>=2 && pResultSet!=0 && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy); while( pWInfo->nLevel>=2 ){ WhereTerm *pTerm, *pEnd; pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 && (pLoop->wsFlags & WHERE_ONEROW)==0 ){ break; } if( (tabUsed & pLoop->maskSelf)!=0 ) break; pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) ){ break; } } if( pTerm<pEnd ) break; WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId)); pWInfo->nLevel--; nTabList--; } } WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; |
︙ | ︙ | |||
5823 5824 5825 5826 5827 5828 5829 | pWInfo->okOnePass = 1; pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ | < < | 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 | pWInfo->okOnePass = 1; pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ notReady = ~(Bitmask)0; for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){ Table *pTab; /* Table to open */ int iDb; /* Index of database containing table/index */ struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ /* Do nothing */ |
︙ | ︙ | |||
5865 5866 5867 5868 5869 5870 5871 | SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } #ifndef SQLITE_OMIT_AUTOMATIC_INDEX | | | 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 | SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } #ifndef SQLITE_OMIT_AUTOMATIC_INDEX if( (pLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel); }else #endif if( pLoop->wsFlags & WHERE_INDEXED ){ Index *pIx = pLoop->u.btree.pIndex; KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); /* FIXME: As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */ |
︙ | ︙ | |||
5988 5989 5990 5991 5992 5993 5994 | && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int ws = pLoop->wsFlags; if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } | | | 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 | && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int ws = pLoop->wsFlags; if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } if( (ws & WHERE_INDEXED)!=0 && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); } } /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can |
︙ | ︙ |
Changes to test/autoindex1.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # If the library is not compiled with automatic index support then # skip all tests in this file. # ifcapable {!autoindex} { finish_test return } # With automatic index turned off, we do a full scan of the T2 table do_test autoindex1-100 { db eval { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,11); INSERT INTO t1 VALUES(2,22); | > > > > > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # If the library is not compiled with automatic index support then # skip all tests in this file. # ifcapable {!autoindex} { finish_test return } # Setup for logging db close sqlite3_shutdown test_sqlite3_log [list lappend ::log] set ::log [list] sqlite3 db test.db # With automatic index turned off, we do a full scan of the T2 table do_test autoindex1-100 { db eval { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,11); INSERT INTO t1 VALUES(2,22); |
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 | } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988} do_test autoindex1-111 { db status step } {7} do_test autoindex1-112 { db status autoindex } {7} # The same test as above, but this time the T2 query is a subquery rather # than a join. do_test autoindex1-200 { db eval { PRAGMA automatic_index=OFF; SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1; | > > > > > > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988} do_test autoindex1-111 { db status step } {7} do_test autoindex1-112 { db status autoindex } {7} do_test autoindex1-113 { set ::log } {SQLITE_WARNING_AUTOINDEX {automatic index on t2(c)}} db close sqlite3_shutdown test_sqlite3_log sqlite3_initialize sqlite3 db test.db # The same test as above, but this time the T2 query is a subquery rather # than a join. do_test autoindex1-200 { db eval { PRAGMA automatic_index=OFF; SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1; |
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 | do_test autoindex1-212 { db status autoindex } {7} # Modify the second table of the join while the join is in progress # do_test autoindex1-300 { set r {} | > > > > > > | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | do_test autoindex1-212 { db status autoindex } {7} # Modify the second table of the join while the join is in progress # do_execsql_test autoindex1-299 { UPDATE sqlite_stat1 SET stat='10000' WHERE tbl='t2'; ANALYZE sqlite_master; EXPLAIN QUERY PLAN SELECT b, d FROM t1 CROSS JOIN t2 ON (c=a); } {/AUTOMATIC COVERING INDEX/} do_test autoindex1-300 { set r {} db eval {SELECT b, d FROM t1 CROSS JOIN t2 ON (c=a)} { lappend r $b $d db eval {UPDATE t2 SET d=d+1} } set r } {11 911 22 922 33 933 44 944 55 955 66 966 77 977 88 988} do_test autoindex1-310 { db eval {SELECT d FROM t2 ORDER BY d} |
︙ | ︙ |
Changes to test/boundary3.tcl.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file is automatically generated from a separate TCL script. # This file seeks to exercise integer boundary values. # | < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file is automatically generated from a separate TCL script. # This file seeks to exercise integer boundary values. # set testdir [file dirname $argv0] source $testdir/tester.tcl # Many of the boundary tests depend on a working 64-bit implementation. if {![working_64bit_int]} { finish_test; return } } |
︙ | ︙ | |||
36 37 38 39 40 41 42 | 0x7fffffffff 0x7fffffffffff 0x7fffffffffffff 0x7fffffffffffffff } { set x [expr {wide($x)}] set boundarynum($x) 1 | | | | | | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 0x7fffffffff 0x7fffffffffff 0x7fffffffffffff 0x7fffffffffffffff } { set x [expr {wide($x)}] set boundarynum($x) 1 set boundarynum([expr {wide($x+1)}]) 1 set boundarynum([expr {wide(-($x+1))}]) 1 set boundarynum([expr {wide(-($x+2))}]) 1 set boundarynum([expr {wide($x+$x+1)}]) 1 set boundarynum([expr {wide($x+$x+2)}]) 1 } set x [expr {wide(127)}] for {set i 1} {$i<=9} {incr i} { set boundarynum($x) 1 set boundarynum([expr {wide($x+1)}]) 1 set x [expr {wide($x*128 + 127)}] } # Scramble the $inlist into a random order. # proc scramble {inlist} { set y {} |
︙ | ︙ | |||
112 113 114 115 116 117 118 | puts " db eval \173" puts " CREATE TABLE t1(a,x);" set a 0 foreach r $nums1 { incr a set t1ra($r) $a set t1ar($a) $r | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | puts " db eval \173" puts " CREATE TABLE t1(a,x);" set a 0 foreach r $nums1 { incr a set t1ra($r) $a set t1ar($a) $r set x [format %016x [expr {wide($r)}]] set t1rx($r) $x set t1xr($x) $r puts " INSERT INTO t1(oid,a,x) VALUES($r,$a,'$x');" } puts " CREATE INDEX t1i1 ON t1(a);" puts " CREATE INDEX t1i2 ON t1(x);" puts " \175" |
︙ | ︙ | |||
154 155 156 157 158 159 160 | set i 0 foreach r $nums3 { incr i set r5 $r.5 set r0 $r.0 | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | set i 0 foreach r $nums3 { incr i set r5 $r.5 set r0 $r.0 if {abs($r)<0x7FFFFFFFFFFFFFFF || $r==-9223372036854775808} { set x $t1rx($r) set a $t1ra($r) puts "do_test $tname-2.$i.1 \173" puts " db eval \173" puts " SELECT t1.* FROM t1, t2 WHERE t1.rowid=$r AND t2.a=t1.a" puts " \175" puts "\175 {$a $x}" |
︙ | ︙ |
Changes to test/capi3d.test.
︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 | test_is_readonly capi3d-2.1 {SELECT * FROM sqlite_master} 1 test_is_readonly capi3d-2.2 {CREATE TABLE t1(x)} 0 db eval {CREATE TABLE t1(x)} test_is_readonly capi3d-2.3 {INSERT INTO t1 VALUES(5)} 0 test_is_readonly capi3d-2.4 {UPDATE t1 SET x=x+1 WHERE x<0} 0 test_is_readonly capi3d-2.5 {SELECT * FROM t1} 1 do_test capi3-2.99 { sqlite3_stmt_readonly 0 } 1 # Tests for sqlite3_stmt_busy # do_test capi3d-3.1 { | > > > > > > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | test_is_readonly capi3d-2.1 {SELECT * FROM sqlite_master} 1 test_is_readonly capi3d-2.2 {CREATE TABLE t1(x)} 0 db eval {CREATE TABLE t1(x)} test_is_readonly capi3d-2.3 {INSERT INTO t1 VALUES(5)} 0 test_is_readonly capi3d-2.4 {UPDATE t1 SET x=x+1 WHERE x<0} 0 test_is_readonly capi3d-2.5 {SELECT * FROM t1} 1 ifcapable wal { test_is_readonly capi3d-2.6 {PRAGMA journal_mode=WAL} 0 test_is_readonly capi3d-2.7 {PRAGMA wal_checkpoint} 0 } test_is_readonly capi3d-2.8 {PRAGMA application_id=1234} 0 test_is_readonly capi3d-2.9 {VACUUM} 0 test_is_readonly capi3d-2.10 {PRAGMA integrity_check} 1 do_test capi3-2.99 { sqlite3_stmt_readonly 0 } 1 # Tests for sqlite3_stmt_busy # do_test capi3d-3.1 { |
︙ | ︙ |
Changes to test/e_expr.test.
︙ | ︙ | |||
1290 1291 1292 1293 1294 1295 1296 | set chars [split $str] for {set i [expr [llength $chars]-1]} {$i>=0} {incr i -1} { append ret [lindex $chars $i] } set ret } proc reverse {lhs rhs} { | | | 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 | set chars [split $str] for {set i [expr [llength $chars]-1]} {$i>=0} {incr i -1} { append ret [lindex $chars $i] } set ret } proc reverse {lhs rhs} { string compare [rev $lhs] [rev $rhs] } db collate reverse reverse do_execsql_test e_expr-23.1.1 { CREATE TABLE t1( a TEXT COLLATE NOCASE, b COLLATE REVERSE, c INTEGER, |
︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 | SELECT CASE 'AbC' WHEN 'abc' THEN 'A' WHEN a THEN 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.4 { SELECT CASE a WHEN b THEN 'A' ELSE 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.5 { SELECT CASE b WHEN a THEN 'A' ELSE 'B' END FROM t1 | | | 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 | SELECT CASE 'AbC' WHEN 'abc' THEN 'A' WHEN a THEN 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.4 { SELECT CASE a WHEN b THEN 'A' ELSE 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.5 { SELECT CASE b WHEN a THEN 'A' ELSE 'B' END FROM t1 } {B} do_execsql_test e_expr-23.1.6 { SELECT CASE 55 WHEN '55' THEN 'A' ELSE 'B' END } {B} do_execsql_test e_expr-23.1.7 { SELECT CASE c WHEN '55' THEN 'A' ELSE 'B' END FROM t1 } {A} do_execsql_test e_expr-23.1.8 { |
︙ | ︙ |
Changes to test/memsubsys1.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | # Test 2: Activate PAGECACHE with 20 pages # db close sqlite3_shutdown sqlite3_config_pagecache [expr 1024+$xtra_size] 20 sqlite3_initialize reset_highwater_marks | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | # Test 2: Activate PAGECACHE with 20 pages # db close sqlite3_shutdown sqlite3_config_pagecache [expr 1024+$xtra_size] 20 sqlite3_initialize reset_highwater_marks build_test_db memsubsys1-2 {PRAGMA page_size=1024; PRAGMA mmap_size=0} #show_memstats set MEMORY_MANAGEMENT $sqlite_options(memorymanage) ifcapable !malloc_usable_size { do_test memsubsys1-2.3 { set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2] } [expr ($TEMP_STORE>1 || $MEMORY_MANAGEMENT==0)*1024] } |
︙ | ︙ |
Changes to test/mmap3.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !mmap||!vtab { finish_test return } source $testdir/lock_common.tcl set testprefix mmap3 do_test mmap3-1.0 { |
︙ | ︙ |
Added test/mmapfault.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 | # 2013-05-23 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl ifcapable !mmap { finish_test return } set testprefix mmapfault set a_string_counter 1 proc a_string {n} { global a_string_counter incr a_string_counter string range [string repeat "${a_string_counter}." $n] 1 $n } db func a_string a_string do_test 1-pre { execsql { CREATE TABLE t1(a UNIQUE, b UNIQUE); INSERT INTO t1 VALUES(a_string(200), a_string(300)); INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; } faultsim_save_and_close } {} do_faultsim_test 1 -prep { faultsim_restore_and_reopen db func a_string a_string breakpoint execsql { PRAGMA mmap_size = 1000000; PRAGMA cache_size = 5; BEGIN; INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; } } -body { execsql { INSERT INTO t1 VALUES(a_string(200), a_string(300)) } } -test { faultsim_test_result {0 {}} if {[sqlite3_get_autocommit db]} { sqlite3 db2 test.db set nRow [db2 one {SELECT count(*) FROM t1}] if {$nRow!=4} { error "Database content appears incorrect (1)" } db2 close } execsql { INSERT INTO t1 VALUES(a_string(201), a_string(301)) } set nRow [db one {SELECT count(*) FROM t1}] if {$nRow!=5 && $nRow!=66 && $nRow!=65} { error "Database content appears incorrect (2) ($nRow)" } catch { execsql COMMIT } } finish_test |
Changes to test/pcache.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 47 48 49 50 51 52 53 | } {current 0 max 0 min 0 recyclable 0} do_test pcache-1.2 { sqlite3 db test.db execsql { PRAGMA cache_size=12; PRAGMA auto_vacuum=0; } pcache_stats } {current 1 max 12 min 10 recyclable 1} do_test pcache-1.3 { execsql { BEGIN; | > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | } {current 0 max 0 min 0 recyclable 0} do_test pcache-1.2 { sqlite3 db test.db execsql { PRAGMA cache_size=12; PRAGMA auto_vacuum=0; PRAGMA mmap_size=0; } pcache_stats } {current 1 max 12 min 10 recyclable 1} do_test pcache-1.3 { execsql { BEGIN; |
︙ | ︙ |
Changes to test/percentile.test.
︙ | ︙ | |||
176 177 178 179 180 181 182 | UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5; SELECT percentile(x,50) from t1; } } {1 {Inf input to percentile()}} # Million-row Inputs # | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | UPDATE t1 SET x=-1.0e300*1.0e300 WHERE rowid=5; SELECT percentile(x,50) from t1; } } {1 {Inf input to percentile()}} # Million-row Inputs # ifcapable vtab { do_test percentile-2.0 { load_static_extension db wholenumber execsql { CREATE VIRTUAL TABLE nums USING wholenumber; CREATE TABLE t3(x); INSERT INTO t3 SELECT value-1 FROM nums WHERE value BETWEEN 1 AND 500000; INSERT INTO t3 SELECT value*10 FROM nums WHERE value BETWEEN 500000 AND 999999; SELECT count(*) FROM t3; } } {1000000} foreach {in out} { 0 0.0 100 9999990.0 50 2749999.5 10 99999.9 } { do_test percentile-2.1.$in { execsql { SELECT percentile(x, $in) from t3; } } $out } } finish_test |
Changes to test/select9.test.
︙ | ︙ | |||
445 446 447 448 449 450 451 452 453 454 | } {~/SCAN TABLE/} ;# Uses indices with "x, y" do_test select9-5.3 { db eval { EXPLAIN QUERY PLAN SELECT x, y FROM v5 WHERE +x='12345' ORDER BY y; } } {/SCAN TABLE/} ;# Full table scan if the "+x" prevents index usage. finish_test | > > > > > > > > > > > > > > > > > > | 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 | } {~/SCAN TABLE/} ;# Uses indices with "x, y" do_test select9-5.3 { db eval { EXPLAIN QUERY PLAN SELECT x, y FROM v5 WHERE +x='12345' ORDER BY y; } } {/SCAN TABLE/} ;# Full table scan if the "+x" prevents index usage. # 2013-07-09: Ticket [490a4b7235624298]: # "WHERE 0" on the first element of a UNION causes an assertion fault # do_execsql_test select9-6.1 { CREATE TABLE t61(a); CREATE TABLE t62(b); INSERT INTO t61 VALUES(111); INSERT INTO t62 VALUES(222); SELECT a FROM t61 WHERE 0 UNION SELECT b FROM t62; } {222} do_execsql_test select9-6.2 { SELECT a FROM t61 WHERE 0 UNION ALL SELECT b FROM t62; } {222} do_execsql_test select9-6.3 { SELECT a FROM t61 UNION SELECT b FROM t62 WHERE 0; } {111} finish_test |
Changes to test/shell1.test.
︙ | ︙ | |||
393 394 395 396 397 398 399 | # .import FILE TABLE Import data from FILE into TABLE do_test shell1-3.11.1 { catchcmd "test.db" ".import" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell1-3.11.2 { catchcmd "test.db" ".import FOO" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} | | | | | 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | # .import FILE TABLE Import data from FILE into TABLE do_test shell1-3.11.1 { catchcmd "test.db" ".import" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell1-3.11.2 { catchcmd "test.db" ".import FOO" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} #do_test shell1-3.11.2 { # catchcmd "test.db" ".import FOO BAR" #} {1 {Error: no such table: BAR}} do_test shell1-3.11.3 { # too many arguments catchcmd "test.db" ".import FOO BAR BAD" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} # .indices ?TABLE? Show names of all indices # If TABLE specified, only show indices for tables |
︙ | ︙ | |||
705 706 707 708 709 710 711 712 713 714 715 716 717 718 | catchcmd test.db \ ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');" } "0 {(123) hello\n456}" do_test shell1-3-29.1 { catchcmd "test.db" ".print this is a test" } {0 {this is a test}} # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); | > > > > > > > > > | 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | catchcmd test.db \ ".log stdout\nSELECT coalesce(sqlite_log(123,'hello'),'456');" } "0 {(123) hello\n456}" do_test shell1-3-29.1 { catchcmd "test.db" ".print this is a test" } {0 {this is a test}} # dot-command argument quoting do_test shell1-3-30.1 { catchcmd {test.db} {.print "this\"is'a\055test" 'this\"is\\a\055test'} } {0 {this"is'a-test this\"is\\a\055test}} do_test shell1-3-31.1 { catchcmd {test.db} {.print "this\nis\ta\\test" 'this\nis\ta\\test'} } [list 0 "this\nis\ta\\test this\\nis\\ta\\\\test"] # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); |
︙ | ︙ |
Changes to test/shell5.test.
︙ | ︙ | |||
41 42 43 44 45 46 47 | # .import FILE TABLE Import data from FILE into TABLE do_test shell5-1.1.1 { catchcmd "test.db" ".import" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell5-1.1.2 { catchcmd "test.db" ".import FOO" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} | | | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # .import FILE TABLE Import data from FILE into TABLE do_test shell5-1.1.1 { catchcmd "test.db" ".import" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} do_test shell5-1.1.2 { catchcmd "test.db" ".import FOO" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} #do_test shell5-1.1.2 { # catchcmd "test.db" ".import FOO BAR" #} {1 {Error: no such table: BAR}} do_test shell5-1.1.3 { # too many arguments catchcmd "test.db" ".import FOO BAR BAD" } {1 {Error: unknown command or invalid arguments: "import". Enter ".help" for help}} # .separator STRING Change separator used by output mode and .import do_test shell1-1.2.1 { |
︙ | ︙ | |||
97 98 99 100 101 102 103 | # import file with 1 row, 1 column (expecting 2 cols) do_test shell5-1.4.3 { set in [open shell5.csv w] puts $in "1" close $in set res [catchcmd "test.db" {.import shell5.csv t1}] | | | | > | 97 98 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 | # import file with 1 row, 1 column (expecting 2 cols) do_test shell5-1.4.3 { set in [open shell5.csv w] puts $in "1" close $in set res [catchcmd "test.db" {.import shell5.csv t1}] } {1 {shell5.csv:1: expected 2 columns but found 1 - filling the rest with NULL}} # import file with 1 row, 3 columns (expecting 2 cols) do_test shell5-1.4.4 { set in [open shell5.csv w] puts $in "1|2|3" close $in set res [catchcmd "test.db" {.import shell5.csv t1}] } {1 {shell5.csv:1: expected 2 columns but found 3 - extras ignored}} # import file with 1 row, 2 columns do_test shell5-1.4.5 { set in [open shell5.csv w] puts $in "1|2" close $in set res [catchcmd "test.db" {DELETE FROM t1; .import shell5.csv t1 SELECT COUNT(*) FROM t1;}] } {0 1} # import file with 2 rows, 2 columns # note we end up with 3 rows because of the 1 row # imported above. do_test shell5-1.4.6 { |
︙ | ︙ | |||
193 194 195 196 197 198 199 | SELECT length(b) FROM t1 WHERE a='8';}] } {0 999} # try importing into a table with a large number of columns. # This is limited by SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999. set cols 999 do_test shell5-1.6.1 { | < | > > > < < | > | > > > > > > > > > > > > > > | 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 242 243 244 245 | SELECT length(b) FROM t1 WHERE a='8';}] } {0 999} # try importing into a table with a large number of columns. # This is limited by SQLITE_MAX_VARIABLE_NUMBER, which defaults to 999. set cols 999 do_test shell5-1.6.1 { set data {} for {set i 1} {$i<$cols} {incr i} { append data "c$i|" } append data "c$cols\n"; for {set i 1} {$i<$cols} {incr i} { append data "$i|" } append data "$cols" set in [open shell5.csv w] puts $in $data close $in set res [catchcmd "test.db" {.import shell5.csv t2 SELECT COUNT(*) FROM t2;}] } {0 1} # try importing a large number of rows set rows 9999 do_test shell5-1.7.1 { set in [open shell5.csv w] puts $in a for {set i 1} {$i<=$rows} {incr i} { puts $in $i } close $in set res [catchcmd "test.db" {.mode csv .import shell5.csv t3 SELECT COUNT(*) FROM t3;}] } [list 0 $rows] # Inport from a pipe. (Unix only, as it requires "awk") if {$tcl_platform(platform)=="unix"} { do_test shell5-1.8 { file delete -force test.db catchcmd test.db {.mode csv .import "|awk 'END{print \"x,y\";for(i=1;i<=5;i++){print i \",this is \" i}}'" t1 SELECT * FROM t1;} } {0 {1,"this is 1" 2,"this is 2" 3,"this is 3" 4,"this is 4" 5,"this is 5"}} } finish_test |
Changes to test/spellfix.test.
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 | } {ae} do_execsql_test 1.13 { SELECT next_char('','vocab','w'); } {r} do_test 1.14 { catchsql {SELECT next_char('','xyzzy','a')} } {1 {no such table: xyzzy}} do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm'); SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5; } {psalm 4} | > > > > > > > > > > > > > > > > | 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 | } {ae} do_execsql_test 1.13 { SELECT next_char('','vocab','w'); } {r} do_test 1.14 { catchsql {SELECT next_char('','xyzzy','a')} } {1 {no such table: xyzzy}} do_execsql_test 1.20 { CREATE TABLE vocab2(w TEXT); CREATE INDEX vocab2w ON vocab2(w COLLATE nocase); INSERT INTO vocab2 VALUES('abc'), ('ABD'), ('aBe'), ('AbF'); SELECT next_char('ab', 'vocab2', 'w', null, 'nocase'); } {cDeF} do_execsql_test 1.21 { SELECT next_char('ab','vocab2','w',null,null); } {c} do_execsql_test 1.22 { SELECT next_char('AB','vocab2','w',null,'NOCASE'); } {cDeF} do_execsql_test 1.23 { SELECT next_char('ab','vocab2','w',null,'binary'); } {c} do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm'); SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5; } {psalm 4} |
︙ | ︙ |
Added test/tkt-868145d012.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 | # 2013 March 05 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. Specifically, # it tests that ticket [868145d012a1] is fixed. # set testdir [file dirname $argv0] source $testdir/tester.tcl do_execsql_test tkt-868145d012.100 { CREATE TABLE p ( id INTEGER PRIMARY KEY, uid VARCHAR(36), t INTEGER ); CREATE TABLE pa ( id INTEGER PRIMARY KEY, a_uid VARCHAR(36) ); CREATE TABLE a ( id INTEGER PRIMARY KEY, uid VARCHAR(36), t INTEGER ); INSERT INTO pa VALUES(1,'1234'); INSERT INTO pa VALUES(2,'2345'); INSERT INTO p VALUES(3,'1234',97); INSERT INTO p VALUES(4,'1234',98); INSERT INTO a VALUES(5,'1234',98); INSERT INTO a VALUES(6,'1234',99); } {} do_execsql_test tkt-868145d012.110 { SELECT DISTINCT pa.id, p.id, a.id FROM pa LEFT JOIN p ON p.uid='1234' LEFT JOIN a ON a.uid=pa.a_uid WHERE a.t=p.t ; } {1 4 5} do_execsql_test tkt-868145d012.120 { SELECT DISTINCT pa.id, p.id, a.id FROM pa LEFT JOIN p ON p.uid='1234' LEFT JOIN a ON a.uid=pa.a_uid AND a.t=p.t ORDER BY 1, 2, 3 ; } {1 3 {} 1 4 5 2 3 {} 2 4 {}} finish_test |
Changes to test/transitive1.test.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 | } {20 20 20} do_execsql_test transitive1-210 { SELECT * FROM t2 WHERE a=b AND c=b AND c>=20 ORDER BY +a; } {3 3 3 20 20 20} do_execsql_test transitive1-220 { SELECT * FROM t2 WHERE a=b AND c=b AND c<=20 ORDER BY +a; } {20 20 20 100 100 100} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 97 98 99 100 101 102 103 104 105 | } {20 20 20} do_execsql_test transitive1-210 { SELECT * FROM t2 WHERE a=b AND c=b AND c>=20 ORDER BY +a; } {3 3 3 20 20 20} do_execsql_test transitive1-220 { SELECT * FROM t2 WHERE a=b AND c=b AND c<=20 ORDER BY +a; } {20 20 20 100 100 100} # Test cases for ticket [[d805526eae253103] 2013-07-08 # "Incorrect join result or assertion fault due to transitive constraints" # do_execsql_test transitive1-300 { CREATE TABLE t301(w INTEGER PRIMARY KEY, x); CREATE TABLE t302(y INTEGER UNIQUE, z); INSERT INTO t301 VALUES(1,2),(3,4),(5,6); INSERT INTO t302 VALUES(1,3),(3,6),(5,7); SELECT * FROM t301 CROSS JOIN t302 WHERE w=y AND y IS NOT NULL ORDER BY +w; } {1 2 1 3 3 4 3 6 5 6 5 7} do_execsql_test transitive1-301 { SELECT * FROM t301 CROSS JOIN t302 WHERE w=y AND y IS NOT NULL ORDER BY w; } {1 2 1 3 3 4 3 6 5 6 5 7} do_execsql_test transitive1-310 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y>1 ORDER BY +w } {3 4 3 6 5 6 5 7} do_execsql_test transitive1-311 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y>1 ORDER BY w } {3 4 3 6 5 6 5 7} do_execsql_test transitive1-312 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y>1 ORDER BY w DESC } {5 6 5 7 3 4 3 6} do_execsql_test transitive1-320 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y BETWEEN 2 AND 4; } {3 4 3 6} do_execsql_test transitive1-331 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y BETWEEN 1 AND 4 ORDER BY w; } {1 2 1 3 3 4 3 6} do_execsql_test transitive1-332 { SELECT * FROM t301 CROSS JOIN t302 ON w=y WHERE y BETWEEN 1 AND 4 ORDER BY w DESC; } {3 4 3 6 1 2 1 3} finish_test |
Changes to test/wal6.test.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # Changing to WAL mode in one connection forces the change in others. # db close forcedelete test.db set all_journal_modes {delete persist truncate memory off} foreach jmode $all_journal_modes { | > | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 97 98 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 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 | #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] set testprefix wal6 source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # Changing to WAL mode in one connection forces the change in others. # db close forcedelete test.db set all_journal_modes {delete persist truncate memory off} foreach jmode $all_journal_modes { do_test wal6-1.0.$jmode { sqlite3 db test.db execsql "PRAGMA journal_mode = $jmode;" } $jmode do_test wal6-1.1.$jmode { execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1,2); SELECT * FROM t1; } } {1 2} # Under Windows, you'll get an error trying to delete # a file this is already opened. Close the first connection # so the other tests work. if {$tcl_platform(platform)=="windows"} { if {$jmode=="persist" || $jmode=="truncate"} { db close } } do_test wal6-1.2.$jmode { sqlite3 db2 test.db execsql { PRAGMA journal_mode=WAL; INSERT INTO t1 VALUES(3,4); SELECT * FROM t1 ORDER BY a; } db2 } {wal 1 2 3 4} if {$tcl_platform(platform)=="windows"} { if {$jmode=="persist" || $jmode=="truncate"} { sqlite3 db test.db } } do_test wal6-1.3.$jmode { execsql { SELECT * FROM t1 ORDER BY a; } } {1 2 3 4} db close db2 close forcedelete test.db } #------------------------------------------------------------------------- # Test that SQLITE_BUSY_SNAPSHOT is returned as expected. # reset_db sqlite3 db2 test.db do_execsql_test 2.1 { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b TEXT); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); BEGIN; SELECT * FROM t1; } {wal 1 one 2 two} do_test 2.2 { execsql { SELECT * FROM t1; INSERT INTO t1 VALUES(3, 'three'); } db2 } {1 one 2 two} do_catchsql_test 2.3 { INSERT INTO t1 VALUES('x', 'x') } {1 {database is locked}} do_test 2.4 { list [sqlite3_errcode db] [sqlite3_extended_errcode db] } {SQLITE_BUSY SQLITE_BUSY_SNAPSHOT} do_execsql_test 2.5 { SELECT * FROM t1; COMMIT; INSERT INTO t1 VALUES('x', 'x') } {1 one 2 two} proc test3 {prefix} { do_test $prefix.1 { execsql { SELECT count(*) FROM t1 } } {0} do_test $prefix.2 { execsql { INSERT INTO t1 VALUES('x', 'x') } db2 } {} do_test $prefix.3 { execsql { INSERT INTO t1 VALUES('y', 'y') } } {} do_test $prefix.4 { execsql { SELECT count(*) FROM t1 } } {2} } do_execsql_test 2.6.1 { DELETE FROM t1 } test3 2.6.2 db func test3 test3 do_execsql_test 2.6.3 { DELETE FROM t1 } db eval {SELECT test3('2.6.4')} do_test 2.x { db2 close } {} #------------------------------------------------------------------------- # Check that if BEGIN IMMEDIATE fails, it does not leave the user with # an open read-transaction (unless one was already open before the BEGIN # IMMEDIATE). Even if there are other active VMs. # proc test4 {prefix} { do_test $prefix.1 { catchsql { BEGIN IMMEDIATE } } {1 {database is locked}} do_test $prefix.2 { execsql { COMMIT } db2 } {} do_test $prefix.3 { execsql { BEGIN IMMEDIATE } } {} do_test $prefix.4 { execsql { COMMIT } } {} } reset_db sqlite3 db2 test.db do_execsql_test 3.1 { PRAGMA journal_mode = WAL; CREATE TABLE ab(a PRIMARY KEY, b); } {wal} do_test 3.2.1 { execsql { BEGIN; INSERT INTO ab VALUES(1, 2); } db2 } {} test4 3.2.2 db func test4 test4 do_test 3.3.1 { execsql { BEGIN; INSERT INTO ab VALUES(3, 4); } db2 } {} db eval {SELECT test4('3.3.2')} do_test 3.x { db2 close } {} finish_test |
Changes to test/where2.test.
︙ | ︙ | |||
302 303 304 305 306 307 308 309 310 311 312 313 314 315 | do_test where2-6.6 { queryplan { SELECT b.* FROM t1 a, t1 b WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) ORDER BY +b.w } } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] # Ticket #2249. Make sure the OR optimization is not attempted if # comparisons between columns of different affinities are needed. # do_test where2-6.7 { execsql { CREATE TABLE t2249a(a TEXT UNIQUE); | > > | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | do_test where2-6.6 { queryplan { SELECT b.* FROM t1 a, t1 b WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10) ORDER BY +b.w } } [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx] if {[permutation] != "no_optimization"} { # Ticket #2249. Make sure the OR optimization is not attempted if # comparisons between columns of different affinities are needed. # do_test where2-6.7 { execsql { CREATE TABLE t2249a(a TEXT UNIQUE); |
︙ | ︙ | |||
469 470 471 472 473 474 475 476 477 478 479 480 481 482 | } {1 2 3 2 3 sort} do_test where2-7.4 { cksort { create unique index i9y on t9(y); select * from t8, t9 where a=1 and y=3 order by b, x } } {1 2 3 2 3 nosort} # Ticket #1807. Using IN constrains on multiple columns of # a multi-column index. # ifcapable subquery { do_test where2-8.1 { execsql { | > > | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | } {1 2 3 2 3 sort} do_test where2-7.4 { cksort { create unique index i9y on t9(y); select * from t8, t9 where a=1 and y=3 order by b, x } } {1 2 3 2 3 nosort} } ;# if {[permutation] != "no_optimization"} # Ticket #1807. Using IN constrains on multiple columns of # a multi-column index. # ifcapable subquery { do_test where2-8.1 { execsql { |
︙ | ︙ |
Changes to test/where3.test.
︙ | ︙ | |||
431 432 433 434 435 436 437 438 439 440 | do_test where3-6.$cnt.8 { set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y" append sql " JOIN t6z USING(a) " append sql $::predicate db eval $sql } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_test where3-6.$cnt.8 { set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y" append sql " JOIN t6z USING(a) " append sql $::predicate db eval $sql } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} } do_execsql_test where3-7-setup { CREATE TABLE t71(x1 INTEGER PRIMARY KEY, y1); CREATE TABLE t72(x2 INTEGER PRIMARY KEY, y2); CREATE TABLE t73(x3, y3); CREATE TABLE t74(x4, y4); INSERT INTO t71 VALUES(123,234); INSERT INTO t72 VALUES(234,345); INSERT INTO t73 VALUES(123,234); INSERT INTO t74 VALUES(234,345); INSERT INTO t74 VALUES(234,678); } {} foreach disabled_opt {none omit-noop-join all} { optimization_control db all 1 optimization_control db $disabled_opt 0 do_execsql_test where3-7.$disabled_opt.1 { SELECT x1 FROM t71 LEFT JOIN t72 ON x2=y1; } {123} do_execsql_test where3-7.$disabled_opt.2 { SELECT x1 FROM t71 LEFT JOIN t72 ON x2=y1 WHERE y2 IS NULL; } {} do_execsql_test where3-7.$disabled_opt.3 { SELECT x1 FROM t71 LEFT JOIN t72 ON x2=y1 WHERE y2 IS NOT NULL; } {123} do_execsql_test where3-7.$disabled_opt.4 { SELECT x1 FROM t71 LEFT JOIN t72 ON x2=y1 AND y2 IS NULL; } {123} do_execsql_test where3-7.$disabled_opt.5 { SELECT x1 FROM t71 LEFT JOIN t72 ON x2=y1 AND y2 IS NOT NULL; } {123} do_execsql_test where3-7.$disabled_opt.6 { SELECT x3 FROM t73 LEFT JOIN t72 ON x2=y3; } {123} do_execsql_test where3-7.$disabled_opt.7 { SELECT DISTINCT x3 FROM t73 LEFT JOIN t72 ON x2=y3; } {123} do_execsql_test where3-7.$disabled_opt.8 { SELECT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123 123} do_execsql_test where3-7.$disabled_opt.9 { SELECT DISTINCT x3 FROM t73 LEFT JOIN t74 ON x4=y3; } {123} } finish_test |
Added test/wild001.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 97 98 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 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 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 | # 2013-07-01 # # 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. # #*********************************************************************** # # This is a test case from content taken "from the wild". In this # particular instance, the query was provided with permission by # Elan Feingold on 2013-06-27. His message on the SQLite mailing list # on that date reads: # #------------------------------------------------------------------------------ # > Can you send (1) the schema (2) the query that is giving problems, and (3) # > the content of the sqlite_stat1 table after you have run ANALYZE? If you # > can combine all of the above into a script, that would be great! # > # > If you send (1..3) above and you give us written permission to include the # > query in our test suite, that would be off-the-chain terrific. # # Please find items 1..3 in this file: http://www.plexapp.com/elan/sqlite_bug.txt # # You have our permission to include the query in your test suite. # # Thanks for an amazing product. #----------------------------------------------------------------------------- # # This test case merely creates the schema and populates SQLITE_STAT1 and # SQLITE_STAT3 then runs an EXPLAIN QUERY PLAN to ensure that the right plan # is discovered. This test case may need to be adjusted for future revisions # of the query planner manage to select a better query plan. The query plan # shown here is known to be very fast with the original data. # # This test should work the same with and without SQLITE_ENABLE_STAT3 # ############################################################################### set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !stat3 { finish_test return } do_execsql_test wild001.01 { CREATE TABLE "items" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "secid" integer, "parent_id" integer, "metadata_type" integer, "guid" varchar(255), "media_item_count" integer, "title" varchar(255), "title_sort" varchar(255) COLLATE NOCASE, "original_title" varchar(255), "studio" varchar(255), "rating" float, "rating_count" integer, "tagline" varchar(255), "summary" text, "trivia" text, "quotes" text, "content_rating" varchar(255), "content_rating_age" integer, "index" integer, "absolute_index" integer, "duration" integer, "user_thumb_url" varchar(255), "user_art_url" varchar(255), "user_banner_url" varchar(255), "user_music_url" varchar(255), "user_fields" varchar(255), "tags_genre" varchar(255), "tags_collection" varchar(255), "tags_director" varchar(255), "tags_writer" varchar(255), "tags_star" varchar(255), "originally_available_at" datetime, "available_at" datetime, "expires_at" datetime, "refreshed_at" datetime, "year" integer, "added_at" datetime, "created_at" datetime, "updated_at" datetime, "deleted_at" datetime, "tags_country" varchar(255), "extra_data" varchar(255), "hash" varchar(255)); CREATE INDEX "i_secid" ON "items" ("secid" ); CREATE INDEX "i_parent_id" ON "items" ("parent_id" ); CREATE INDEX "i_created_at" ON "items" ("created_at" ); CREATE INDEX "i_index" ON "items" ("index" ); CREATE INDEX "i_title" ON "items" ("title" ); CREATE INDEX "i_title_sort" ON "items" ("title_sort" ); CREATE INDEX "i_guid" ON "items" ("guid" ); CREATE INDEX "i_metadata_type" ON "items" ("metadata_type" ); CREATE INDEX "i_deleted_at" ON "items" ("deleted_at" ); CREATE INDEX "i_secid_ex1" ON "items" ("secid", "metadata_type", "added_at" ); CREATE INDEX "i_hash" ON "items" ("hash" ); CREATE TABLE "settings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "account_id" integer, "guid" varchar(255), "rating" float, "view_offset" integer, "view_count" integer, "last_viewed_at" datetime, "created_at" datetime, "updated_at" datetime); CREATE INDEX "s_account_id" ON "settings" ("account_id" ); CREATE INDEX "s_guid" ON "settings" ("guid" ); ANALYZE; INSERT INTO sqlite_stat1 VALUES('settings','s_guid','4740 1'); INSERT INTO sqlite_stat1 VALUES('settings','s_account_id','4740 4740'); INSERT INTO sqlite_stat1 VALUES('items','i_hash','27316 2'); INSERT INTO sqlite_stat1 VALUES('items','i_secid_ex1','27316 6829 4553 3'); INSERT INTO sqlite_stat1 VALUES('items','i_deleted_at','27316 27316'); INSERT INTO sqlite_stat1 VALUES('items','i_metadata_type','27316 6829'); INSERT INTO sqlite_stat1 VALUES('items','i_guid','27316 2'); INSERT INTO sqlite_stat1 VALUES('items','i_title_sort','27316 2'); INSERT INTO sqlite_stat1 VALUES('items','i_title','27316 2'); INSERT INTO sqlite_stat1 VALUES('items','i_index','27316 144'); INSERT INTO sqlite_stat1 VALUES('items','i_created_at','27316 2'); INSERT INTO sqlite_stat1 VALUES('items','i_parent_id','27316 15'); INSERT INTO sqlite_stat1 VALUES('items','i_secid','27316 6829'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,150,150,'com.plexapp.agents.thetvdb://153021/2/9?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,198,198,'com.plexapp.agents.thetvdb://194031/1/10?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,526,526,'com.plexapp.agents.thetvdb://71256/12/92?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,923,923,'com.plexapp.agents.thetvdb://71256/15/16?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1008,1008,'com.plexapp.agents.thetvdb://71256/15/93?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1053,1053,'com.plexapp.agents.thetvdb://71256/16/21?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1068,1068,'com.plexapp.agents.thetvdb://71256/16/35?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1235,1235,'com.plexapp.agents.thetvdb://71256/17/44?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1255,1255,'com.plexapp.agents.thetvdb://71256/17/62?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1573,1573,'com.plexapp.agents.thetvdb://71663/20/9?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,1580,1580,'com.plexapp.agents.thetvdb://71663/21/16?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2000,2000,'com.plexapp.agents.thetvdb://73141/9/8?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2107,2107,'com.plexapp.agents.thetvdb://73244/6/17?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2256,2256,'com.plexapp.agents.thetvdb://74845/4/7?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2408,2408,'com.plexapp.agents.thetvdb://75978/2/21?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2634,2634,'com.plexapp.agents.thetvdb://79126/1/1?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,2962,2962,'com.plexapp.agents.thetvdb://79274/3/94?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3160,3160,'com.plexapp.agents.thetvdb://79274/5/129?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3161,3161,'com.plexapp.agents.thetvdb://79274/5/12?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3688,3688,'com.plexapp.agents.thetvdb://79274/8/62?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,3714,3714,'com.plexapp.agents.thetvdb://79274/8/86?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4002,4002,'com.plexapp.agents.thetvdb://79590/13/17?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4215,4215,'com.plexapp.agents.thetvdb://80727/3/6?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_guid',1,4381,4381,'com.plexapp.agents.thetvdb://83462/3/24?lang=en'); INSERT INTO sqlite_stat3 VALUES('settings','s_account_id',4740,0,0,1); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,1879,1879,'1113f632ccd52ec8b8d7ca3d6d56da4701e48018'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,2721,2721,'1936154b97bb5567163edaebc2806830ae419ccf'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,3035,3035,'1c122331d4b7bfa0dc2c003ab5fb4f7152b9987a'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,3393,3393,'1f81bdbc9acc3321dc592b1a109ca075731b549a'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,6071,6070,'393cf7713efb4519c7a3d1d5403f0d945d15a16a'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,7462,7461,'4677dd37011f8bd9ae7fbbdd3af6dcd8a5b4ab2d'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8435,8434,'4ffa339485334e81a5e12e03a63b6508d76401cf'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,8716,8714,'52a093852e6599dd5004857b7ff5b5b82c7cdb25'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,9107,9104,'561183e39f866d97ec728e9ff16ac4ad01466111'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,10942,10939,'66e99b72e29610f49499ae09ee04a376210d1f08'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,12143,12139,'71f0602427e173dc2c551535f73fdb6885fe4302'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,14962,14958,'8ca8e4dfba696019830c19ab8a32c7ece9d8534b'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15179,15174,'8ebf1a5cf33f8ada1fc5853ac06ac4d7e074f825'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,15375,15370,'908bc211bebdf21c79d2d2b54ebaa442ac1f5cae'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18215,18210,'ab29e4e18ec5a14fef95aa713d69e31c045a22c1'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18615,18610,'ae84c008cc0c338bf4f28d798a88575746452f6d'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,18649,18644,'aec7c901353e115aa5307e94018ba7507bec3a45'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,19517,19512,'b75025fbf2e9c504e3c1197ff1b69250402a31f8'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,21251,21245,'c7d32f0e3a8f3a0a3dbd00833833d2ccee62f0fd'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,23616,23610,'dd5ff61479a9bd4100de802515d9dcf72d46f07a'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24287,24280,'e3db00034301b7555419d4ef6f64769298d5845e'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,24949,24942,'ea336abd197ecd7013854a25a4f4eb9dea7927c6'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',1,25574,25567,'f018ea5182ec3f32768ca1c3cefbf3ad160ec20b'); INSERT INTO sqlite_stat3 VALUES('items','i_hash',2,26139,26132,'f53709a8d81c12cb0f4f8d58004a25dd063de67c'); INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',25167,0,0,2); INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',736,25167,1,3); INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',15,25903,2,4); INSERT INTO sqlite_stat3 VALUES('items','i_secid_ex1',1398,25918,3,5); INSERT INTO sqlite_stat3 VALUES('items','i_deleted_at',27316,0,0,NULL); INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',2149,0,0,1); INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',411,2149,1,2); INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',1440,2560,2,3); INSERT INTO sqlite_stat3 VALUES('items','i_metadata_type',23316,4000,3,4); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,215,215,'com.plexapp.agents.imdb://tt0065702?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,711,711,'com.plexapp.agents.imdb://tt0198781?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,987,986,'com.plexapp.agents.imdb://tt0454876?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1004,1002,'com.plexapp.agents.imdb://tt0464154?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1056,1053,'com.plexapp.agents.imdb://tt0499549?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1120,1116,'com.plexapp.agents.imdb://tt0903624?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1250,1245,'com.plexapp.agents.imdb://tt1268799?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1270,1264,'com.plexapp.agents.imdb://tt1320261?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',2,1376,1369,'com.plexapp.agents.imdb://tt1772341?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,3035,3027,'com.plexapp.agents.thetvdb://153021/3/14?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6071,6063,'com.plexapp.agents.thetvdb://71173/1/18?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,6342,6334,'com.plexapp.agents.thetvdb://71256/13/4?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,9107,9099,'com.plexapp.agents.thetvdb://72389/2/19?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,11740,11732,'com.plexapp.agents.thetvdb://73893/2/13?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,12143,12135,'com.plexapp.agents.thetvdb://73976/4/23?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,15179,15171,'com.plexapp.agents.thetvdb://75897/16/12?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17408,17400,'com.plexapp.agents.thetvdb://76808/2/16?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,17984,17976,'com.plexapp.agents.thetvdb://77068/1/16?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,18215,18207,'com.plexapp.agents.thetvdb://77259/1/1?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,21251,21243,'com.plexapp.agents.thetvdb://78957/8/2?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,24287,24279,'com.plexapp.agents.thetvdb://80337/5/8?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25513,25505,'com.plexapp.agents.thetvdb://82226/6?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,25548,25540,'com.plexapp.agents.thetvdb://82339/2/10?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_guid',1,26770,26762,'com.plexapp.agents.thetvdb://86901/1/3?lang=en'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1524,0,0,''); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',2,3034,1391,'Attack of the Giant Squid'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',51,4742,2895,'Brad Sherwood'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',11,4912,2996,'Brian Williams'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',39,5847,3857,'Chip Esten'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,6071,4015,'Chuck Versus the DeLorean'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,7625,5436,'Denny Siegel'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',30,8924,6618,'Episode 1'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',29,9015,6629,'Episode 2'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',32,9082,6643,'Episode 3'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',28,9135,6654,'Episode 4'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',26,9183,6665,'Episode 5'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',27,9229,6677,'Episode 6'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',22,9266,6688,'Episode 7'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',20,9298,6699,'Episode 8'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',55,11750,8817,'Greg Proops'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,12143,9120,'Hardware Jungle'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',33,14712,11435,'Kathy Greenwood'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',3,15179,11840,'Last Call'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,18215,14601,'Nature or Nurture?'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',12,18241,14623,'Neil DeGrasse Tyson'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',68,19918,16144,'Pilot'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',7,21251,17298,'Reza Aslan'); INSERT INTO sqlite_stat3 VALUES('items','i_title_sort',1,24287,20035,'Technoviking'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1524,0,0,''); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,3035,1429,'Anderson Can''t Dance'); INSERT INTO sqlite_stat3 VALUES('items','i_title',51,4782,2991,'Brad Sherwood'); INSERT INTO sqlite_stat3 VALUES('items','i_title',11,4936,3079,'Brian Williams'); INSERT INTO sqlite_stat3 VALUES('items','i_title',39,5694,3783,'Chip Esten'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,6071,4100,'Clive Warren'); INSERT INTO sqlite_stat3 VALUES('items','i_title',12,7144,5078,'Denny Siegel'); INSERT INTO sqlite_stat3 VALUES('items','i_title',30,8249,6097,'Episode 1'); INSERT INTO sqlite_stat3 VALUES('items','i_title',29,8340,6108,'Episode 2'); INSERT INTO sqlite_stat3 VALUES('items','i_title',32,8407,6122,'Episode 3'); INSERT INTO sqlite_stat3 VALUES('items','i_title',28,8460,6133,'Episode 4'); INSERT INTO sqlite_stat3 VALUES('items','i_title',26,8508,6144,'Episode 5'); INSERT INTO sqlite_stat3 VALUES('items','i_title',27,8554,6156,'Episode 6'); INSERT INTO sqlite_stat3 VALUES('items','i_title',22,8591,6167,'Episode 7'); INSERT INTO sqlite_stat3 VALUES('items','i_title',20,8623,6178,'Episode 8'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,9107,6537,'Fat Albert and the Cosby Kids'); INSERT INTO sqlite_stat3 VALUES('items','i_title',55,10539,7843,'Greg Proops'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,12143,9276,'Iron Age Remains'); INSERT INTO sqlite_stat3 VALUES('items','i_title',33,13118,10143,'Kathy Greenwood'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,15179,11972,'Mink'); INSERT INTO sqlite_stat3 VALUES('items','i_title',68,17411,14035,'Pilot'); INSERT INTO sqlite_stat3 VALUES('items','i_title',2,18214,14727,'Reflections'); INSERT INTO sqlite_stat3 VALUES('items','i_title',4,21250,17481,'The Apartment'); INSERT INTO sqlite_stat3 VALUES('items','i_title',1,24287,20283,'The Simpsons Already Did It'); INSERT INTO sqlite_stat3 VALUES('items','i_index',4315,95,2,1); INSERT INTO sqlite_stat3 VALUES('items','i_index',1553,4410,3,2); INSERT INTO sqlite_stat3 VALUES('items','i_index',1485,5963,4,3); INSERT INTO sqlite_stat3 VALUES('items','i_index',1414,7448,5,4); INSERT INTO sqlite_stat3 VALUES('items','i_index',1367,8862,6,5); INSERT INTO sqlite_stat3 VALUES('items','i_index',1328,10229,7,6); INSERT INTO sqlite_stat3 VALUES('items','i_index',1161,11557,8,7); INSERT INTO sqlite_stat3 VALUES('items','i_index',1108,12718,9,8); INSERT INTO sqlite_stat3 VALUES('items','i_index',1033,13826,10,9); INSERT INTO sqlite_stat3 VALUES('items','i_index',1014,14859,11,10); INSERT INTO sqlite_stat3 VALUES('items','i_index',929,15873,12,11); INSERT INTO sqlite_stat3 VALUES('items','i_index',906,16802,13,12); INSERT INTO sqlite_stat3 VALUES('items','i_index',844,17708,14,13); INSERT INTO sqlite_stat3 VALUES('items','i_index',690,18552,15,14); INSERT INTO sqlite_stat3 VALUES('items','i_index',655,19242,16,15); INSERT INTO sqlite_stat3 VALUES('items','i_index',625,19897,17,16); INSERT INTO sqlite_stat3 VALUES('items','i_index',579,20522,18,17); INSERT INTO sqlite_stat3 VALUES('items','i_index',555,21101,19,18); INSERT INTO sqlite_stat3 VALUES('items','i_index',526,21656,20,19); INSERT INTO sqlite_stat3 VALUES('items','i_index',501,22182,21,20); INSERT INTO sqlite_stat3 VALUES('items','i_index',459,22683,22,21); INSERT INTO sqlite_stat3 VALUES('items','i_index',439,23142,23,22); INSERT INTO sqlite_stat3 VALUES('items','i_index',315,23581,24,23); INSERT INTO sqlite_stat3 VALUES('items','i_index',192,24177,26,25); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1851,0,0,NULL); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',373,1857,2,'2011-10-22 14:54:39'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',595,2230,3,'2011-10-22 14:54:41'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',337,2825,4,'2011-10-22 14:54:43'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',361,3378,8,'2011-10-22 14:54:54'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',160,3739,9,'2011-10-22 14:54:56'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',315,4000,11,'2011-10-22 14:54:59'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',321,4334,13,'2011-10-22 14:55:02'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1292,4723,16,'2011-10-22 14:55:06'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,6015,17,'2011-10-22 14:55:07'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,9107,2677,'2012-09-04 18:07:50'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',313,9717,3270,'2012-10-18 16:50:21'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',450,10030,3271,'2012-10-18 16:50:22'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',389,10668,3275,'2012-10-18 16:50:26'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',796,11057,3276,'2012-10-18 16:51:06'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',161,12041,3280,'2012-10-19 19:52:37'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',135,13281,4186,'2013-02-19 00:56:10'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1063,13416,4187,'2013-02-19 00:56:11'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',797,14479,4188,'2013-02-19 00:56:13'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',147,15276,4189,'2013-02-19 00:56:15'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',346,15423,4190,'2013-02-19 00:56:16'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,18215,6436,'2013-05-05 14:09:54'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',2,21251,8122,'2013-05-24 15:25:45'); INSERT INTO sqlite_stat3 VALUES('items','i_created_at',1,24287,11116,'2013-05-26 14:17:39'); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2560,0,0,NULL); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',18,3022,31,2350); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',10,6068,285,8150); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',158,6346,315,8949); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',34,9094,562,18831); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',20,12139,794,22838); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',134,14033,886,24739); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',159,14167,887,24740); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14326,888,24741); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,14487,889,24742); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,14648,890,24743); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',157,14772,891,24744); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',126,15043,894,24747); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',40,15169,895,24748); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15243,898,24753); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',138,15404,899,24754); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',160,15542,900,24755); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15702,901,24756); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',161,15863,902,24757); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',124,16024,903,24758); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',155,16148,904,24759); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',26,18208,1043,29704); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',2,21251,1282,32952); INSERT INTO sqlite_stat3 VALUES('items','i_parent_id',13,24279,1583,36068); INSERT INTO sqlite_stat3 VALUES('items','i_secid',25167,0,0,2); INSERT INTO sqlite_stat3 VALUES('items','i_secid',736,25167,1,3); INSERT INTO sqlite_stat3 VALUES('items','i_secid',15,25903,2,4); INSERT INTO sqlite_stat3 VALUES('items','i_secid',1398,25918,3,5); ANALYZE sqlite_master; explain query plan select items.title from items join items as child on child.parent_id=items.id join items as grandchild on grandchild.parent_id=child.id join settings on settings.guid=grandchild.guid and settings.account_id=1 where items.metadata_type=2 and items.secid=2 and settings.last_viewed_at is not null group by items.id order by settings.last_viewed_at desc limit 10; } [list \ 0 0 3 {SEARCH TABLE settings USING INDEX s_account_id (account_id=?)} \ 0 1 2 {SEARCH TABLE items AS grandchild USING INDEX i_guid (guid=?)} \ 0 2 1 {SEARCH TABLE items AS child USING INTEGER PRIMARY KEY (rowid=?)} \ 0 3 0 {SEARCH TABLE items USING INTEGER PRIMARY KEY (rowid=?)} \ 0 0 0 {USE TEMP B-TREE FOR GROUP BY} \ 0 0 0 {USE TEMP B-TREE FOR ORDER BY}] finish_test |