Fossil SCM

Update the built-in SQLite to the latest 3.34.0 alpha.

drh 2020-10-13 12:19 trunk
Commit 2ec0dc29f386cc5dc16a34f64e3f23be89a899717d5b713cf11cc46845086ebe
3 files changed +60 -27 +521 -151 +1 -1
+60 -27
--- src/shell.c
+++ src/shell.c
@@ -11198,10 +11198,12 @@
1119811198
#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
1119911199
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
1120011200
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
1120111201
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
1120211202
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
11203
+#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
11204
+#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
1120311205
1120411206
/*
1120511207
** Macros for testing and setting shellFlgs
1120611208
*/
1120711209
#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
@@ -13724,17 +13726,21 @@
1372413726
UNUSED_PARAMETER(azNotUsed);
1372513727
if( nArg!=3 || azArg==0 ) return 0;
1372613728
zTable = azArg[0];
1372713729
zType = azArg[1];
1372813730
zSql = azArg[2];
13731
+ int dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
13732
+ int noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
1372913733
13730
- if( strcmp(zTable, "sqlite_sequence")==0 ){
13731
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
13732
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
13733
- raw_printf(p->out, "ANALYZE sqlite_schema;\n");
13734
+ if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
13735
+ if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
13736
+ }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
13737
+ if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
1373413738
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
1373513739
return 0;
13740
+ }else if( dataOnly ){
13741
+ /* no-op */
1373613742
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
1373713743
char *zIns;
1373813744
if( !p->writableSchema ){
1373913745
raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
1374013746
p->writableSchema = 1;
@@ -13903,12 +13909,14 @@
1390313909
".databases List names and files of attached databases",
1390413910
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
1390513911
".dbinfo ?DB? Show status information about the database",
1390613912
".dump ?TABLE? Render database content as SQL",
1390713913
" Options:",
13908
- " --preserve-rowids Include ROWID values in the output",
13914
+ " --data-only Output only INSERT statements",
1390913915
" --newlines Allow unescaped newline characters in output",
13916
+ " --nosys Omit system tables (ex: \"sqlite_stat1\")",
13917
+ " --preserve-rowids Include ROWID values in the output",
1391013918
" TABLE is a LIKE pattern for the tables to dump",
1391113919
" Additional LIKE patterns can be given in subsequent arguments",
1391213920
".echo on|off Turn command echo on or off",
1391313921
".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
1391413922
" Other Modes:",
@@ -14029,12 +14037,13 @@
1402914037
#endif
1403014038
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
1403114039
".save FILE Write in-memory database into FILE",
1403214040
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
1403314041
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
14034
- " Options:",
14035
- " --indent Try to pretty-print the schema",
14042
+ " Options:",
14043
+ " --indent Try to pretty-print the schema",
14044
+ " --nosys Omit objects whose names start with \"sqlite_\"",
1403614045
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
1403714046
" Options:",
1403814047
" --init Create a new SELFTEST table",
1403914048
" -v Verbose output",
1404014049
".separator COL ?ROW? Change the column and row separators",
@@ -17705,11 +17714,13 @@
1770517714
char *zLike = 0;
1770617715
char *zSql;
1770717716
int i;
1770817717
int savedShowHeader = p->showHeader;
1770917718
int savedShellFlags = p->shellFlgs;
17710
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
17719
+ ShellClearFlag(p,
17720
+ SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
17721
+ |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
1771117722
for(i=1; i<nArg; i++){
1771217723
if( azArg[i][0]=='-' ){
1771317724
const char *z = azArg[i]+1;
1771417725
if( z[0]=='-' ) z++;
1771517726
if( strcmp(z,"preserve-rowids")==0 ){
@@ -17724,10 +17735,16 @@
1772417735
#endif
1772517736
}else
1772617737
if( strcmp(z,"newlines")==0 ){
1772717738
ShellSetFlag(p, SHFLG_Newlines);
1772817739
}else
17740
+ if( strcmp(z,"data-only")==0 ){
17741
+ ShellSetFlag(p, SHFLG_DumpDataOnly);
17742
+ }else
17743
+ if( strcmp(z,"nosys")==0 ){
17744
+ ShellSetFlag(p, SHFLG_DumpNoSys);
17745
+ }else
1772917746
{
1773017747
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
1773117748
rc = 1;
1773217749
sqlite3_free(zLike);
1773317750
goto meta_command_exit;
@@ -17740,15 +17757,17 @@
1774017757
}
1774117758
}
1774217759
1774317760
open_db(p, 0);
1774417761
17745
- /* When playing back a "dump", the content might appear in an order
17746
- ** which causes immediate foreign key constraints to be violated.
17747
- ** So disable foreign-key constraint enforcement to prevent problems. */
17748
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
17749
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
17762
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17763
+ /* When playing back a "dump", the content might appear in an order
17764
+ ** which causes immediate foreign key constraints to be violated.
17765
+ ** So disable foreign-key constraint enforcement to prevent problems. */
17766
+ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
17767
+ raw_printf(p->out, "BEGIN TRANSACTION;\n");
17768
+ }
1775017769
p->writableSchema = 0;
1775117770
p->showHeader = 0;
1775217771
/* Set writable_schema=ON since doing so forces SQLite to initialize
1775317772
** as much of the schema as it can even if the sqlite_schema table is
1775417773
** corrupt. */
@@ -17762,26 +17781,30 @@
1776217781
" ORDER BY tbl_name='sqlite_sequence', rowid",
1776317782
zLike
1776417783
);
1776517784
run_schema_dump_query(p,zSql);
1776617785
sqlite3_free(zSql);
17767
- zSql = sqlite3_mprintf(
17768
- "SELECT sql FROM sqlite_schema "
17769
- "WHERE (%s) AND sql NOT NULL"
17770
- " AND type IN ('index','trigger','view')",
17771
- zLike
17772
- );
17773
- run_table_dump_query(p, zSql);
17774
- sqlite3_free(zSql);
17786
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17787
+ zSql = sqlite3_mprintf(
17788
+ "SELECT sql FROM sqlite_schema "
17789
+ "WHERE (%s) AND sql NOT NULL"
17790
+ " AND type IN ('index','trigger','view')",
17791
+ zLike
17792
+ );
17793
+ run_table_dump_query(p, zSql);
17794
+ sqlite3_free(zSql);
17795
+ }
1777517796
sqlite3_free(zLike);
1777617797
if( p->writableSchema ){
1777717798
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
1777817799
p->writableSchema = 0;
1777917800
}
1778017801
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
1778117802
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
17782
- raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
17803
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17804
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
17805
+ }
1778317806
p->showHeader = savedShowHeader;
1778417807
p->shellFlgs = savedShellFlags;
1778517808
}else
1778617809
1778717810
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -18216,20 +18239,20 @@
1821618239
utf8_printf(p->out, "\n");
1821718240
}
1821818241
while( (nSkip--)>0 ){
1821918242
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
1822018243
}
18221
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
18244
+ zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
1822218245
if( zSql==0 ){
1822318246
import_cleanup(&sCtx);
1822418247
shell_out_of_memory();
1822518248
}
1822618249
nByte = strlen30(zSql);
1822718250
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
1822818251
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
1822918252
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
18230
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
18253
+ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
1823118254
char cSep = '(';
1823218255
while( xRead(&sCtx) ){
1823318256
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
1823418257
cSep = ',';
1823518258
if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -18246,11 +18269,11 @@
1824618269
utf8_printf(p->out, "%s\n", zCreate);
1824718270
}
1824818271
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
1824918272
sqlite3_free(zCreate);
1825018273
if( rc ){
18251
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
18274
+ utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
1825218275
sqlite3_errmsg(p->db));
1825318276
import_cleanup(&sCtx);
1825418277
rc = 1;
1825518278
goto meta_command_exit;
1825618279
}
@@ -19102,10 +19125,11 @@
1910219125
char *zErrMsg = 0;
1910319126
const char *zDiv = "(";
1910419127
const char *zName = 0;
1910519128
int iSchema = 0;
1910619129
int bDebug = 0;
19130
+ int bNoSystemTabs = 0;
1910719131
int ii;
1910819132
1910919133
open_db(p, 0);
1911019134
memcpy(&data, p, sizeof(data));
1911119135
data.showHeader = 0;
@@ -19114,14 +19138,20 @@
1911419138
for(ii=1; ii<nArg; ii++){
1911519139
if( optionMatch(azArg[ii],"indent") ){
1911619140
data.cMode = data.mode = MODE_Pretty;
1911719141
}else if( optionMatch(azArg[ii],"debug") ){
1911819142
bDebug = 1;
19143
+ }else if( optionMatch(azArg[ii],"nosys") ){
19144
+ bNoSystemTabs = 1;
19145
+ }else if( azArg[ii][0]=='-' ){
19146
+ utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
19147
+ rc = 1;
19148
+ goto meta_command_exit;
1911919149
}else if( zName==0 ){
1912019150
zName = azArg[ii];
1912119151
}else{
19122
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
19152
+ raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
1912319153
rc = 1;
1912419154
goto meta_command_exit;
1912519155
}
1912619156
}
1912719157
if( zName!=0 ){
@@ -19203,11 +19233,14 @@
1920319233
appendText(&sSelect, " ESCAPE '\\' ", 0);
1920419234
}
1920519235
appendText(&sSelect, " AND ", 0);
1920619236
sqlite3_free(zQarg);
1920719237
}
19208
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
19238
+ if( bNoSystemTabs ){
19239
+ appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
19240
+ }
19241
+ appendText(&sSelect, "sql IS NOT NULL"
1920919242
" ORDER BY snum, rowid", 0);
1921019243
if( bDebug ){
1921119244
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
1921219245
}else{
1921319246
rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
1921419247
--- src/shell.c
+++ src/shell.c
@@ -11198,10 +11198,12 @@
11198 #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
11199 #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
11200 #define SHFLG_CountChanges 0x00000020 /* .changes setting */
11201 #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
11202 #define SHFLG_HeaderSet 0x00000080 /* .header has been used */
 
 
11203
11204 /*
11205 ** Macros for testing and setting shellFlgs
11206 */
11207 #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
@@ -13724,17 +13726,21 @@
13724 UNUSED_PARAMETER(azNotUsed);
13725 if( nArg!=3 || azArg==0 ) return 0;
13726 zTable = azArg[0];
13727 zType = azArg[1];
13728 zSql = azArg[2];
 
 
13729
13730 if( strcmp(zTable, "sqlite_sequence")==0 ){
13731 raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
13732 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
13733 raw_printf(p->out, "ANALYZE sqlite_schema;\n");
13734 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
13735 return 0;
 
 
13736 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
13737 char *zIns;
13738 if( !p->writableSchema ){
13739 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
13740 p->writableSchema = 1;
@@ -13903,12 +13909,14 @@
13903 ".databases List names and files of attached databases",
13904 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
13905 ".dbinfo ?DB? Show status information about the database",
13906 ".dump ?TABLE? Render database content as SQL",
13907 " Options:",
13908 " --preserve-rowids Include ROWID values in the output",
13909 " --newlines Allow unescaped newline characters in output",
 
 
13910 " TABLE is a LIKE pattern for the tables to dump",
13911 " Additional LIKE patterns can be given in subsequent arguments",
13912 ".echo on|off Turn command echo on or off",
13913 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
13914 " Other Modes:",
@@ -14029,12 +14037,13 @@
14029 #endif
14030 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
14031 ".save FILE Write in-memory database into FILE",
14032 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
14033 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
14034 " Options:",
14035 " --indent Try to pretty-print the schema",
 
14036 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
14037 " Options:",
14038 " --init Create a new SELFTEST table",
14039 " -v Verbose output",
14040 ".separator COL ?ROW? Change the column and row separators",
@@ -17705,11 +17714,13 @@
17705 char *zLike = 0;
17706 char *zSql;
17707 int i;
17708 int savedShowHeader = p->showHeader;
17709 int savedShellFlags = p->shellFlgs;
17710 ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
 
 
17711 for(i=1; i<nArg; i++){
17712 if( azArg[i][0]=='-' ){
17713 const char *z = azArg[i]+1;
17714 if( z[0]=='-' ) z++;
17715 if( strcmp(z,"preserve-rowids")==0 ){
@@ -17724,10 +17735,16 @@
17724 #endif
17725 }else
17726 if( strcmp(z,"newlines")==0 ){
17727 ShellSetFlag(p, SHFLG_Newlines);
17728 }else
 
 
 
 
 
 
17729 {
17730 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
17731 rc = 1;
17732 sqlite3_free(zLike);
17733 goto meta_command_exit;
@@ -17740,15 +17757,17 @@
17740 }
17741 }
17742
17743 open_db(p, 0);
17744
17745 /* When playing back a "dump", the content might appear in an order
17746 ** which causes immediate foreign key constraints to be violated.
17747 ** So disable foreign-key constraint enforcement to prevent problems. */
17748 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
17749 raw_printf(p->out, "BEGIN TRANSACTION;\n");
 
 
17750 p->writableSchema = 0;
17751 p->showHeader = 0;
17752 /* Set writable_schema=ON since doing so forces SQLite to initialize
17753 ** as much of the schema as it can even if the sqlite_schema table is
17754 ** corrupt. */
@@ -17762,26 +17781,30 @@
17762 " ORDER BY tbl_name='sqlite_sequence', rowid",
17763 zLike
17764 );
17765 run_schema_dump_query(p,zSql);
17766 sqlite3_free(zSql);
17767 zSql = sqlite3_mprintf(
17768 "SELECT sql FROM sqlite_schema "
17769 "WHERE (%s) AND sql NOT NULL"
17770 " AND type IN ('index','trigger','view')",
17771 zLike
17772 );
17773 run_table_dump_query(p, zSql);
17774 sqlite3_free(zSql);
 
 
17775 sqlite3_free(zLike);
17776 if( p->writableSchema ){
17777 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
17778 p->writableSchema = 0;
17779 }
17780 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
17781 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
17782 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
 
 
17783 p->showHeader = savedShowHeader;
17784 p->shellFlgs = savedShellFlags;
17785 }else
17786
17787 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -18216,20 +18239,20 @@
18216 utf8_printf(p->out, "\n");
18217 }
18218 while( (nSkip--)>0 ){
18219 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
18220 }
18221 zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
18222 if( zSql==0 ){
18223 import_cleanup(&sCtx);
18224 shell_out_of_memory();
18225 }
18226 nByte = strlen30(zSql);
18227 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18228 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
18229 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
18230 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
18231 char cSep = '(';
18232 while( xRead(&sCtx) ){
18233 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
18234 cSep = ',';
18235 if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -18246,11 +18269,11 @@
18246 utf8_printf(p->out, "%s\n", zCreate);
18247 }
18248 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
18249 sqlite3_free(zCreate);
18250 if( rc ){
18251 utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
18252 sqlite3_errmsg(p->db));
18253 import_cleanup(&sCtx);
18254 rc = 1;
18255 goto meta_command_exit;
18256 }
@@ -19102,10 +19125,11 @@
19102 char *zErrMsg = 0;
19103 const char *zDiv = "(";
19104 const char *zName = 0;
19105 int iSchema = 0;
19106 int bDebug = 0;
 
19107 int ii;
19108
19109 open_db(p, 0);
19110 memcpy(&data, p, sizeof(data));
19111 data.showHeader = 0;
@@ -19114,14 +19138,20 @@
19114 for(ii=1; ii<nArg; ii++){
19115 if( optionMatch(azArg[ii],"indent") ){
19116 data.cMode = data.mode = MODE_Pretty;
19117 }else if( optionMatch(azArg[ii],"debug") ){
19118 bDebug = 1;
 
 
 
 
 
 
19119 }else if( zName==0 ){
19120 zName = azArg[ii];
19121 }else{
19122 raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
19123 rc = 1;
19124 goto meta_command_exit;
19125 }
19126 }
19127 if( zName!=0 ){
@@ -19203,11 +19233,14 @@
19203 appendText(&sSelect, " ESCAPE '\\' ", 0);
19204 }
19205 appendText(&sSelect, " AND ", 0);
19206 sqlite3_free(zQarg);
19207 }
19208 appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
 
 
 
19209 " ORDER BY snum, rowid", 0);
19210 if( bDebug ){
19211 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
19212 }else{
19213 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
19214
--- src/shell.c
+++ src/shell.c
@@ -11198,10 +11198,12 @@
11198 #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
11199 #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
11200 #define SHFLG_CountChanges 0x00000020 /* .changes setting */
11201 #define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
11202 #define SHFLG_HeaderSet 0x00000080 /* .header has been used */
11203 #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
11204 #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
11205
11206 /*
11207 ** Macros for testing and setting shellFlgs
11208 */
11209 #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
@@ -13724,17 +13726,21 @@
13726 UNUSED_PARAMETER(azNotUsed);
13727 if( nArg!=3 || azArg==0 ) return 0;
13728 zTable = azArg[0];
13729 zType = azArg[1];
13730 zSql = azArg[2];
13731 int dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
13732 int noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
13733
13734 if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
13735 if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
13736 }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
13737 if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
13738 }else if( strncmp(zTable, "sqlite_", 7)==0 ){
13739 return 0;
13740 }else if( dataOnly ){
13741 /* no-op */
13742 }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
13743 char *zIns;
13744 if( !p->writableSchema ){
13745 raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
13746 p->writableSchema = 1;
@@ -13903,12 +13909,14 @@
13909 ".databases List names and files of attached databases",
13910 ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
13911 ".dbinfo ?DB? Show status information about the database",
13912 ".dump ?TABLE? Render database content as SQL",
13913 " Options:",
13914 " --data-only Output only INSERT statements",
13915 " --newlines Allow unescaped newline characters in output",
13916 " --nosys Omit system tables (ex: \"sqlite_stat1\")",
13917 " --preserve-rowids Include ROWID values in the output",
13918 " TABLE is a LIKE pattern for the tables to dump",
13919 " Additional LIKE patterns can be given in subsequent arguments",
13920 ".echo on|off Turn command echo on or off",
13921 ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
13922 " Other Modes:",
@@ -14029,12 +14037,13 @@
14037 #endif
14038 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
14039 ".save FILE Write in-memory database into FILE",
14040 ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
14041 ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
14042 " Options:",
14043 " --indent Try to pretty-print the schema",
14044 " --nosys Omit objects whose names start with \"sqlite_\"",
14045 ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
14046 " Options:",
14047 " --init Create a new SELFTEST table",
14048 " -v Verbose output",
14049 ".separator COL ?ROW? Change the column and row separators",
@@ -17705,11 +17714,13 @@
17714 char *zLike = 0;
17715 char *zSql;
17716 int i;
17717 int savedShowHeader = p->showHeader;
17718 int savedShellFlags = p->shellFlgs;
17719 ShellClearFlag(p,
17720 SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
17721 |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
17722 for(i=1; i<nArg; i++){
17723 if( azArg[i][0]=='-' ){
17724 const char *z = azArg[i]+1;
17725 if( z[0]=='-' ) z++;
17726 if( strcmp(z,"preserve-rowids")==0 ){
@@ -17724,10 +17735,16 @@
17735 #endif
17736 }else
17737 if( strcmp(z,"newlines")==0 ){
17738 ShellSetFlag(p, SHFLG_Newlines);
17739 }else
17740 if( strcmp(z,"data-only")==0 ){
17741 ShellSetFlag(p, SHFLG_DumpDataOnly);
17742 }else
17743 if( strcmp(z,"nosys")==0 ){
17744 ShellSetFlag(p, SHFLG_DumpNoSys);
17745 }else
17746 {
17747 raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
17748 rc = 1;
17749 sqlite3_free(zLike);
17750 goto meta_command_exit;
@@ -17740,15 +17757,17 @@
17757 }
17758 }
17759
17760 open_db(p, 0);
17761
17762 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17763 /* When playing back a "dump", the content might appear in an order
17764 ** which causes immediate foreign key constraints to be violated.
17765 ** So disable foreign-key constraint enforcement to prevent problems. */
17766 raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
17767 raw_printf(p->out, "BEGIN TRANSACTION;\n");
17768 }
17769 p->writableSchema = 0;
17770 p->showHeader = 0;
17771 /* Set writable_schema=ON since doing so forces SQLite to initialize
17772 ** as much of the schema as it can even if the sqlite_schema table is
17773 ** corrupt. */
@@ -17762,26 +17781,30 @@
17781 " ORDER BY tbl_name='sqlite_sequence', rowid",
17782 zLike
17783 );
17784 run_schema_dump_query(p,zSql);
17785 sqlite3_free(zSql);
17786 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17787 zSql = sqlite3_mprintf(
17788 "SELECT sql FROM sqlite_schema "
17789 "WHERE (%s) AND sql NOT NULL"
17790 " AND type IN ('index','trigger','view')",
17791 zLike
17792 );
17793 run_table_dump_query(p, zSql);
17794 sqlite3_free(zSql);
17795 }
17796 sqlite3_free(zLike);
17797 if( p->writableSchema ){
17798 raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
17799 p->writableSchema = 0;
17800 }
17801 sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
17802 sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
17803 if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
17804 raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
17805 }
17806 p->showHeader = savedShowHeader;
17807 p->shellFlgs = savedShellFlags;
17808 }else
17809
17810 if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
@@ -18216,20 +18239,20 @@
18239 utf8_printf(p->out, "\n");
18240 }
18241 while( (nSkip--)>0 ){
18242 while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
18243 }
18244 zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
18245 if( zSql==0 ){
18246 import_cleanup(&sCtx);
18247 shell_out_of_memory();
18248 }
18249 nByte = strlen30(zSql);
18250 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
18251 import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
18252 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
18253 char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
18254 char cSep = '(';
18255 while( xRead(&sCtx) ){
18256 zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
18257 cSep = ',';
18258 if( sCtx.cTerm!=sCtx.cColSep ) break;
@@ -18246,11 +18269,11 @@
18269 utf8_printf(p->out, "%s\n", zCreate);
18270 }
18271 rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
18272 sqlite3_free(zCreate);
18273 if( rc ){
18274 utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
18275 sqlite3_errmsg(p->db));
18276 import_cleanup(&sCtx);
18277 rc = 1;
18278 goto meta_command_exit;
18279 }
@@ -19102,10 +19125,11 @@
19125 char *zErrMsg = 0;
19126 const char *zDiv = "(";
19127 const char *zName = 0;
19128 int iSchema = 0;
19129 int bDebug = 0;
19130 int bNoSystemTabs = 0;
19131 int ii;
19132
19133 open_db(p, 0);
19134 memcpy(&data, p, sizeof(data));
19135 data.showHeader = 0;
@@ -19114,14 +19138,20 @@
19138 for(ii=1; ii<nArg; ii++){
19139 if( optionMatch(azArg[ii],"indent") ){
19140 data.cMode = data.mode = MODE_Pretty;
19141 }else if( optionMatch(azArg[ii],"debug") ){
19142 bDebug = 1;
19143 }else if( optionMatch(azArg[ii],"nosys") ){
19144 bNoSystemTabs = 1;
19145 }else if( azArg[ii][0]=='-' ){
19146 utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
19147 rc = 1;
19148 goto meta_command_exit;
19149 }else if( zName==0 ){
19150 zName = azArg[ii];
19151 }else{
19152 raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
19153 rc = 1;
19154 goto meta_command_exit;
19155 }
19156 }
19157 if( zName!=0 ){
@@ -19203,11 +19233,14 @@
19233 appendText(&sSelect, " ESCAPE '\\' ", 0);
19234 }
19235 appendText(&sSelect, " AND ", 0);
19236 sqlite3_free(zQarg);
19237 }
19238 if( bNoSystemTabs ){
19239 appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
19240 }
19241 appendText(&sSelect, "sql IS NOT NULL"
19242 " ORDER BY snum, rowid", 0);
19243 if( bDebug ){
19244 utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
19245 }else{
19246 rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
19247
+521 -151
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1171,11 +1171,11 @@
11711171
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
11721172
** [sqlite_version()] and [sqlite_source_id()].
11731173
*/
11741174
#define SQLITE_VERSION "3.34.0"
11751175
#define SQLITE_VERSION_NUMBER 3034000
1176
-#define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"
1176
+#define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"
11771177
11781178
/*
11791179
** CAPI3REF: Run-Time Library Version Numbers
11801180
** KEYWORDS: sqlite3_version sqlite3_sourceid
11811181
**
@@ -88945,11 +88945,12 @@
8894588945
**
8894688946
** Begin a transaction on database P1 if a transaction is not already
8894788947
** active.
8894888948
** If P2 is non-zero, then a write-transaction is started, or if a
8894988949
** read-transaction is already active, it is upgraded to a write-transaction.
88950
-** If P2 is zero, then a read-transaction is started.
88950
+** If P2 is zero, then a read-transaction is started. If P2 is 2 or more
88951
+** then an exclusive transaction is started.
8895188952
**
8895288953
** P1 is the index of the database file on which the transaction is
8895388954
** started. Index 0 is the main database file and index 1 is the
8895488955
** file used for temporary tables. Indices of 2 or more are used for
8895588956
** attached databases.
@@ -88979,10 +88980,11 @@
8897988980
Btree *pBt;
8898088981
int iMeta = 0;
8898188982
8898288983
assert( p->bIsReader );
8898388984
assert( p->readOnly==0 || pOp->p2==0 );
88985
+ assert( pOp->p2>=0 && pOp->p2<=2 );
8898488986
assert( pOp->p1>=0 && pOp->p1<db->nDb );
8898588987
assert( DbMaskTest(p->btreeMask, pOp->p1) );
8898688988
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
8898788989
rc = SQLITE_READONLY;
8898888990
goto abort_due_to_error;
@@ -89842,22 +89844,22 @@
8984289844
}
8984389845
break;
8984489846
}
8984589847
8984689848
89847
-/* Opcode: SeekScan P1 * * * *
89849
+/* Opcode: SeekScan P1 P2 * * *
8984889850
** Synopsis: Scan-ahead up to P1 rows
8984989851
**
8985089852
** This opcode is a prefix opcode to OP_SeekGE. In other words, this
89851
-** opcode must be immediately followed by OP_SeekGE. Furthermore, the
89852
-** OP_SeekGE must be followed by OP_IdxGT. These constraints are
89853
+** opcode must be immediately followed by OP_SeekGE. This constraint is
8985389854
** checked by assert() statements.
8985489855
**
8985589856
** This opcode uses the P1 through P4 operands of the subsequent
8985689857
** OP_SeekGE. In the text that follows, the operands of the subsequent
8985789858
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
89858
-** the P1 operand of this opcode is used, and it is denoted as This.P1.
89859
+** the P1 and P2 operands of this opcode are also used, and are called
89860
+** This.P1 and This.P2.
8985989861
**
8986089862
** This opcode helps to optimize IN operators on a multi-column index
8986189863
** where the IN operator is on the later terms of the index by avoiding
8986289864
** unnecessary seeks on the btree, substituting steps to the next row
8986389865
** of the b-tree instead. A correct answer is obtained if this opcode
@@ -89871,39 +89873,43 @@
8987189873
** then this opcode is a no-op and control passes through into the OP_SeekGE.
8987289874
**
8987389875
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
8987489876
** might be the target row, or it might be near and slightly before the
8987589877
** target row. This opcode attempts to position the cursor on the target
89876
-** row by, perhaps stepping by invoking sqlite3BtreeStep() on the cursor
89878
+** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
8987789879
** between 0 and This.P1 times.
8987889880
**
8987989881
** There are three possible outcomes from this opcode:<ol>
8988089882
**
8988189883
** <li> If after This.P1 steps, the cursor is still point to a place that
8988289884
** is earlier in the btree than the target row,
8988389885
** then fall through into the subsquence OP_SeekGE opcode.
8988489886
**
8988589887
** <li> If the cursor is successfully moved to the target row by 0 or more
89886
-** sqlite3BtreeNext() calls, then jump to the first instruction after the
89887
-** OP_IdxGT opcode - or in other words, skip the next two opcodes.
89888
+** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
89889
+** past the OP_IdxGT opcode that follows the OP_SeekGE.
8988889890
**
8988989891
** <li> If the cursor ends up past the target row (indicating the the target
8989089892
** row does not exist in the btree) then jump to SeekOP.P2.
8989189893
** </ol>
8989289894
*/
8989389895
case OP_SeekScan: {
8989489896
VdbeCursor *pC;
8989589897
int res;
89896
- int n;
89898
+ int nStep;
8989789899
UnpackedRecord r;
8989889900
8989989901
assert( pOp[1].opcode==OP_SeekGE );
89900
- assert( pOp[2].opcode==OP_IdxGT );
89901
- assert( pOp[1].p1==pOp[2].p1 );
89902
- assert( pOp[1].p2==pOp[2].p2 );
89903
- assert( pOp[1].p3==pOp[2].p3 );
89904
- assert( pOp[1].p4.i==pOp[2].p4.i );
89902
+
89903
+ /* pOp->p2 points to the first instruction past the OP_IdxGT that
89904
+ ** follows the OP_SeekGE. */
89905
+ assert( pOp->p2>=(int)(pOp-aOp)+2 );
89906
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
89907
+ assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
89908
+ assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
89909
+ assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
89910
+
8990589911
assert( pOp->p1>0 );
8990689912
pC = p->apCsr[pOp[1].p1];
8990789913
assert( pC!=0 );
8990889914
assert( pC->eCurType==CURTYPE_BTREE );
8990989915
assert( !pC->isTable );
@@ -89913,12 +89919,12 @@
8991389919
printf("... cursor not valid - fall through\n");
8991489920
}
8991589921
#endif
8991689922
break;
8991789923
}
89918
- n = pOp->p1;
89919
- assert( n>=1 );
89924
+ nStep = pOp->p1;
89925
+ assert( nStep>=1 );
8992089926
r.pKeyInfo = pC->pKeyInfo;
8992189927
r.nField = (u16)pOp[1].p4.i;
8992289928
r.default_rc = 0;
8992389929
r.aMem = &aMem[pOp[1].p3];
8992489930
#ifdef SQLITE_DEBUG
@@ -89936,37 +89942,37 @@
8993689942
if( rc ) goto abort_due_to_error;
8993789943
if( res>0 ){
8993889944
seekscan_search_fail:
8993989945
#ifdef SQLITE_DEBUG
8994089946
if( db->flags&SQLITE_VdbeTrace ){
89941
- printf("... %d steps and then skip\n", pOp->p1 - n);
89947
+ printf("... %d steps and then skip\n", pOp->p1 - nStep);
8994289948
}
8994389949
#endif
8994489950
VdbeBranchTaken(1,3);
8994589951
pOp++;
8994689952
goto jump_to_p2;
8994789953
}
8994889954
if( res==0 ){
8994989955
#ifdef SQLITE_DEBUG
8995089956
if( db->flags&SQLITE_VdbeTrace ){
89951
- printf("... %d steps and then success\n", pOp->p1 - n);
89957
+ printf("... %d steps and then success\n", pOp->p1 - nStep);
8995289958
}
8995389959
#endif
8995489960
VdbeBranchTaken(2,3);
89955
- pOp += 2;
89961
+ goto jump_to_p2;
8995689962
break;
8995789963
}
89958
- if( n<=0 ){
89964
+ if( nStep<=0 ){
8995989965
#ifdef SQLITE_DEBUG
8996089966
if( db->flags&SQLITE_VdbeTrace ){
8996189967
printf("... fall through after %d steps\n", pOp->p1);
8996289968
}
8996389969
#endif
8996489970
VdbeBranchTaken(0,3);
8996589971
break;
8996689972
}
89967
- n--;
89973
+ nStep--;
8996889974
rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
8996989975
if( rc ){
8997089976
if( rc==SQLITE_DONE ){
8997189977
rc = SQLITE_OK;
8997289978
goto seekscan_search_fail;
@@ -100066,11 +100072,13 @@
100066100072
** SELECT * FROM t1 WHERE (select a from t1);
100067100073
*/
100068100074
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
100069100075
int op;
100070100076
while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
100071
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
100077
+ assert( pExpr->op==TK_COLLATE
100078
+ || pExpr->op==TK_IF_NULL_ROW
100079
+ || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
100072100080
pExpr = pExpr->pLeft;
100073100081
assert( pExpr!=0 );
100074100082
}
100075100083
op = pExpr->op;
100076100084
if( op==TK_SELECT ){
@@ -112360,11 +112368,11 @@
112360112368
Table *p;
112361112369
int i;
112362112370
char *zColl; /* Dequoted name of collation sequence */
112363112371
sqlite3 *db;
112364112372
112365
- if( (p = pParse->pNewTable)==0 ) return;
112373
+ if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
112366112374
i = p->nCol-1;
112367112375
db = pParse->db;
112368112376
zColl = sqlite3NameFromToken(db, pToken);
112369112377
if( !zColl ) return;
112370112378
@@ -115361,11 +115369,20 @@
115361115369
}
115362115370
v = sqlite3GetVdbe(pParse);
115363115371
if( !v ) return;
115364115372
if( type!=TK_DEFERRED ){
115365115373
for(i=0; i<db->nDb; i++){
115366
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
115374
+ int eTxnType;
115375
+ Btree *pBt = db->aDb[i].pBt;
115376
+ if( pBt && sqlite3BtreeIsReadonly(pBt) ){
115377
+ eTxnType = 0; /* Read txn */
115378
+ }else if( type==TK_EXCLUSIVE ){
115379
+ eTxnType = 2; /* Exclusive txn */
115380
+ }else{
115381
+ eTxnType = 1; /* Write txn */
115382
+ }
115383
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
115367115384
sqlite3VdbeUsesBtree(v, i);
115368115385
}
115369115386
}
115370115387
sqlite3VdbeAddOp0(v, OP_AutoCommit);
115371115388
}
@@ -117348,14 +117365,10 @@
117348117365
** opcode if it is present */
117349117366
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
117350117367
}
117351117368
if( regOut ){
117352117369
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
117353
- if( pIdx->pTable->pSelect ){
117354
- const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
117355
- sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
117356
- }
117357117370
}
117358117371
sqlite3ReleaseTempRange(pParse, regBase, nCol);
117359117372
return regBase;
117360117373
}
117361117374
@@ -138158,11 +138171,11 @@
138158138171
pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
138159138172
}
138160138173
#endif
138161138174
pList = sqlite3ExprListAppend(pParse, pList, pNew);
138162138175
}
138163
- eDest = SRT_Upfrom;
138176
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
138164138177
}else if( pTab->pSelect ){
138165138178
for(i=0; i<pTab->nCol; i++){
138166138179
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
138167138180
}
138168138181
eDest = SRT_Table;
@@ -139111,16 +139124,30 @@
139111139124
ephemTab = pParse->nTab++;
139112139125
addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
139113139126
regArg = pParse->nMem + 1;
139114139127
pParse->nMem += nArg;
139115139128
if( pSrc->nSrc>1 ){
139129
+ Index *pPk = 0;
139116139130
Expr *pRow;
139117139131
ExprList *pList;
139118
- if( pRowid ){
139119
- pRow = sqlite3ExprDup(db, pRowid, 0);
139132
+ if( HasRowid(pTab) ){
139133
+ if( pRowid ){
139134
+ pRow = sqlite3ExprDup(db, pRowid, 0);
139135
+ }else{
139136
+ pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
139137
+ }
139120139138
}else{
139121
- pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
139139
+ i16 iPk; /* PRIMARY KEY column */
139140
+ pPk = sqlite3PrimaryKeyIndex(pTab);
139141
+ assert( pPk!=0 );
139142
+ assert( pPk->nKeyCol==1 );
139143
+ iPk = pPk->aiColumn[0];
139144
+ if( aXRef[iPk]>=0 ){
139145
+ pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
139146
+ }else{
139147
+ pRow = exprRowColumn(pParse, iPk);
139148
+ }
139122139149
}
139123139150
pList = sqlite3ExprListAppend(pParse, 0, pRow);
139124139151
139125139152
for(i=0; i<pTab->nCol; i++){
139126139153
if( aXRef[i]>=0 ){
@@ -139130,11 +139157,11 @@
139130139157
}else{
139131139158
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
139132139159
}
139133139160
}
139134139161
139135
- updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
139162
+ updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
139136139163
sqlite3ExprListDelete(db, pList);
139137139164
eOnePass = ONEPASS_OFF;
139138139165
}else{
139139139166
regRec = ++pParse->nMem;
139140139167
regRowid = ++pParse->nMem;
@@ -142457,11 +142484,16 @@
142457142484
pIn->eEndLoopOp = OP_Noop;
142458142485
}
142459142486
pIn++;
142460142487
}
142461142488
}
142462
- if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
142489
+ testcase( iEq>0
142490
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
142491
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
142492
+ if( iEq>0
142493
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
142494
+ ){
142463142495
sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
142464142496
}
142465142497
}else{
142466142498
pLevel->u.in.nIn = 0;
142467142499
}
@@ -143507,10 +143539,11 @@
143507143539
char *zEndAff = 0; /* Affinity for end of range constraint */
143508143540
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
143509143541
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
143510143542
int omitTable; /* True if we use the index only */
143511143543
int regBignull = 0; /* big-null flag register */
143544
+ int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
143512143545
143513143546
pIdx = pLoop->u.btree.pIndex;
143514143547
iIdxCur = pLevel->iIdxCur;
143515143548
assert( nEq>=pLoop->nSkip );
143516143549
@@ -143652,22 +143685,22 @@
143652143685
VdbeComment((v, "NULL-scan pass ctr"));
143653143686
}
143654143687
143655143688
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
143656143689
assert( op!=0 );
143657
- if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
143658
- assert( op==OP_SeekGE );
143690
+ if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
143659143691
assert( regBignull==0 );
143660143692
/* TUNING: The OP_SeekScan opcode seeks to reduce the number
143661143693
** of expensive seek operations by replacing a single seek with
143662143694
** 1 or more step operations. The question is, how many steps
143663143695
** should we try before giving up and going with a seek. The cost
143664143696
** of a seek is proportional to the logarithm of the of the number
143665143697
** of entries in the tree, so basing the number of steps to try
143666143698
** on the estimated number of rows in the btree seems like a good
143667143699
** guess. */
143668
- sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10);
143700
+ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
143701
+ (pIdx->aiRowLogEst[0]+9)/10);
143669143702
VdbeCoverage(v);
143670143703
}
143671143704
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143672143705
VdbeCoverage(v);
143673143706
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -143748,10 +143781,11 @@
143748143781
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143749143782
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
143750143783
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
143751143784
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
143752143785
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
143786
+ if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
143753143787
}
143754143788
if( regBignull ){
143755143789
/* During a NULL-scan, check to see if we have reached the end of
143756143790
** the NULLs */
143757143791
assert( bSeekPastNull==!bStopAtNull );
@@ -148484,11 +148518,11 @@
148484148518
}
148485148519
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
148486148520
/* "x IN (value, value, ...)" */
148487148521
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
148488148522
}
148489
- if( pProbe->hasStat1 ){
148523
+ if( pProbe->hasStat1 && rLogSize>=10 ){
148490148524
LogEst M, logK, safetyMargin;
148491148525
/* Let:
148492148526
** N = the total number of rows in the table
148493148527
** K = the number of entries on the RHS of the IN operator
148494148528
** M = the number of rows in the table that match terms to the
@@ -148503,11 +148537,12 @@
148503148537
**
148504148538
** Our estimates for M, K, and N might be inaccurate, so we build in
148505148539
** a safety margin of 2 (LogEst: 10) that favors using the IN operator
148506148540
** with the index, as using an index has better worst-case behavior.
148507148541
** If we do not have real sqlite_stat1 data, always prefer to use
148508
- ** the index.
148542
+ ** the index. Do not bother with this optimization on very small
148543
+ ** tables (less than 2 rows) as it is pointless in that case.
148509148544
*/
148510148545
M = pProbe->aiRowLogEst[saved_nEq];
148511148546
logK = estLog(nIn);
148512148547
safetyMargin = 10; /* TUNING: extra weight for indexed IN */
148513148548
if( M + logK + safetyMargin < nIn + rLogSize ){
@@ -209277,10 +209312,11 @@
209277209312
int eDetail; /* FTS5_DETAIL_XXX value */
209278209313
char *zContentExprlist;
209279209314
Fts5Tokenizer *pTok;
209280209315
fts5_tokenizer *pTokApi;
209281209316
int bLock; /* True when table is preparing statement */
209317
+ int ePattern; /* FTS_PATTERN_XXX constant */
209282209318
209283209319
/* Values loaded from the %_config table */
209284209320
int iCookie; /* Incremented when %_config is modified */
209285209321
int pgsz; /* Approximate page size used in %_data */
209286209322
int nAutomerge; /* 'automerge' setting */
@@ -209297,21 +209333,23 @@
209297209333
int bPrefixIndex; /* True to use prefix-indexes */
209298209334
#endif
209299209335
};
209300209336
209301209337
/* Current expected value of %_config table 'version' field */
209302
-#define FTS5_CURRENT_VERSION 4
209338
+#define FTS5_CURRENT_VERSION 4
209303209339
209304209340
#define FTS5_CONTENT_NORMAL 0
209305209341
#define FTS5_CONTENT_NONE 1
209306209342
#define FTS5_CONTENT_EXTERNAL 2
209307209343
209308
-#define FTS5_DETAIL_FULL 0
209309
-#define FTS5_DETAIL_NONE 1
209310
-#define FTS5_DETAIL_COLUMNS 2
209344
+#define FTS5_DETAIL_FULL 0
209345
+#define FTS5_DETAIL_NONE 1
209346
+#define FTS5_DETAIL_COLUMNS 2
209311209347
209312
-
209348
+#define FTS5_PATTERN_NONE 0
209349
+#define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
209350
+#define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */
209313209351
209314209352
static int sqlite3Fts5ConfigParse(
209315209353
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
209316209354
);
209317209355
static void sqlite3Fts5ConfigFree(Fts5Config*);
@@ -209647,12 +209685,11 @@
209647209685
209648209686
static int sqlite3Fts5GetTokenizer(
209649209687
Fts5Global*,
209650209688
const char **azArg,
209651209689
int nArg,
209652
- Fts5Tokenizer**,
209653
- fts5_tokenizer**,
209690
+ Fts5Config*,
209654209691
char **pzErr
209655209692
);
209656209693
209657209694
static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
209658209695
@@ -209777,14 +209814,22 @@
209777209814
};
209778209815
209779209816
/* Parse a MATCH expression. */
209780209817
static int sqlite3Fts5ExprNew(
209781209818
Fts5Config *pConfig,
209819
+ int bPhraseToAnd,
209782209820
int iCol, /* Column on LHS of MATCH operator */
209783209821
const char *zExpr,
209784209822
Fts5Expr **ppNew,
209785209823
char **pzErr
209824
+);
209825
+static int sqlite3Fts5ExprPattern(
209826
+ Fts5Config *pConfig,
209827
+ int bGlob,
209828
+ int iCol,
209829
+ const char *zText,
209830
+ Fts5Expr **pp
209786209831
);
209787209832
209788209833
/*
209789209834
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
209790209835
** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
@@ -209890,10 +209935,14 @@
209890209935
/**************************************************************************
209891209936
** Interface to code in fts5_tokenizer.c.
209892209937
*/
209893209938
209894209939
static int sqlite3Fts5TokenizerInit(fts5_api*);
209940
+static int sqlite3Fts5TokenizerPattern(
209941
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
209942
+ Fts5Tokenizer *pTok
209943
+);
209895209944
/*
209896209945
** End of interface to code in fts5_tokenizer.c.
209897209946
**************************************************************************/
209898209947
209899209948
/**************************************************************************
@@ -212869,11 +212918,11 @@
212869212918
if( p==0 ){
212870212919
*pzErr = sqlite3_mprintf("parse error in tokenize directive");
212871212920
rc = SQLITE_ERROR;
212872212921
}else{
212873212922
rc = sqlite3Fts5GetTokenizer(pGlobal,
212874
- (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
212923
+ (const char**)azArg, (int)nArg, pConfig,
212875212924
pzErr
212876212925
);
212877212926
}
212878212927
}
212879212928
}
@@ -212941,13 +212990,11 @@
212941212990
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
212942212991
** code if an error occurs.
212943212992
*/
212944212993
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
212945212994
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
212946
- return sqlite3Fts5GetTokenizer(
212947
- pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
212948
- );
212995
+ return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
212949212996
}
212950212997
212951212998
/*
212952212999
** Gobble up the first bareword or quoted word from the input buffer zIn.
212953213000
** Return a pointer to the character immediately following the last in
@@ -213635,10 +213682,11 @@
213635213682
char *zErr;
213636213683
int rc;
213637213684
int nPhrase; /* Size of apPhrase array */
213638213685
Fts5ExprPhrase **apPhrase; /* Array of all phrases */
213639213686
Fts5ExprNode *pExpr; /* Result of a successful parse */
213687
+ int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
213640213688
};
213641213689
213642213690
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
213643213691
va_list ap;
213644213692
va_start(ap, zFmt);
@@ -213723,10 +213771,11 @@
213723213771
static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
213724213772
static void fts5ParseFree(void *p){ sqlite3_free(p); }
213725213773
213726213774
static int sqlite3Fts5ExprNew(
213727213775
Fts5Config *pConfig, /* FTS5 Configuration */
213776
+ int bPhraseToAnd,
213728213777
int iCol,
213729213778
const char *zExpr, /* Expression text */
213730213779
Fts5Expr **ppNew,
213731213780
char **pzErr
213732213781
){
@@ -213738,10 +213787,11 @@
213738213787
Fts5Expr *pNew;
213739213788
213740213789
*ppNew = 0;
213741213790
*pzErr = 0;
213742213791
memset(&sParse, 0, sizeof(sParse));
213792
+ sParse.bPhraseToAnd = bPhraseToAnd;
213743213793
pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
213744213794
if( pEngine==0 ){ return SQLITE_NOMEM; }
213745213795
sParse.pConfig = pConfig;
213746213796
213747213797
do {
@@ -213780,10 +213830,11 @@
213780213830
}
213781213831
pNew->pIndex = 0;
213782213832
pNew->pConfig = pConfig;
213783213833
pNew->apExprPhrase = sParse.apPhrase;
213784213834
pNew->nPhrase = sParse.nPhrase;
213835
+ pNew->bDesc = 0;
213785213836
sParse.apPhrase = 0;
213786213837
}
213787213838
}else{
213788213839
sqlite3Fts5ParseNodeFree(sParse.pExpr);
213789213840
}
@@ -213790,10 +213841,85 @@
213790213841
213791213842
sqlite3_free(sParse.apPhrase);
213792213843
*pzErr = sParse.zErr;
213793213844
return sParse.rc;
213794213845
}
213846
+
213847
+/*
213848
+** This function is only called when using the special 'trigram' tokenizer.
213849
+** Argument zText contains the text of a LIKE or GLOB pattern matched
213850
+** against column iCol. This function creates and compiles an FTS5 MATCH
213851
+** expression that will match a superset of the rows matched by the LIKE or
213852
+** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
213853
+** code.
213854
+*/
213855
+static int sqlite3Fts5ExprPattern(
213856
+ Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
213857
+){
213858
+ i64 nText = strlen(zText);
213859
+ char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
213860
+ int rc = SQLITE_OK;
213861
+
213862
+ if( zExpr==0 ){
213863
+ rc = SQLITE_NOMEM;
213864
+ }else{
213865
+ char aSpec[3];
213866
+ int iOut = 0;
213867
+ int i = 0;
213868
+ int iFirst = 0;
213869
+
213870
+ if( bGlob==0 ){
213871
+ aSpec[0] = '_';
213872
+ aSpec[1] = '%';
213873
+ aSpec[2] = 0;
213874
+ }else{
213875
+ aSpec[0] = '*';
213876
+ aSpec[1] = '?';
213877
+ aSpec[2] = '[';
213878
+ }
213879
+
213880
+ while( i<=nText ){
213881
+ if( i==nText
213882
+ || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
213883
+ ){
213884
+ if( i-iFirst>=3 ){
213885
+ int jj;
213886
+ zExpr[iOut++] = '"';
213887
+ for(jj=iFirst; jj<i; jj++){
213888
+ zExpr[iOut++] = zText[jj];
213889
+ if( zText[jj]=='"' ) zExpr[iOut++] = '"';
213890
+ }
213891
+ zExpr[iOut++] = '"';
213892
+ zExpr[iOut++] = ' ';
213893
+ }
213894
+ if( zText[i]==aSpec[2] ){
213895
+ i += 2;
213896
+ if( zText[i-1]=='^' ) i++;
213897
+ while( i<nText && zText[i]!=']' ) i++;
213898
+ }
213899
+ iFirst = i+1;
213900
+ }
213901
+ i++;
213902
+ }
213903
+ if( iOut>0 ){
213904
+ int bAnd = 0;
213905
+ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
213906
+ bAnd = 1;
213907
+ if( pConfig->eDetail==FTS5_DETAIL_NONE ){
213908
+ iCol = pConfig->nCol;
213909
+ }
213910
+ }
213911
+ zExpr[iOut] = '\0';
213912
+ rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
213913
+ }else{
213914
+ *pp = 0;
213915
+ }
213916
+ sqlite3_free(zExpr);
213917
+ }
213918
+
213919
+ return rc;
213920
+}
213795213921
213796213922
/*
213797213923
** Free the expression node object passed as the only argument.
213798213924
*/
213799213925
static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -215167,10 +215293,24 @@
215167215293
215168215294
static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
215169215295
assert( pParse->pExpr==0 );
215170215296
pParse->pExpr = p;
215171215297
}
215298
+
215299
+static int parseGrowPhraseArray(Fts5Parse *pParse){
215300
+ if( (pParse->nPhrase % 8)==0 ){
215301
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
215302
+ Fts5ExprPhrase **apNew;
215303
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
215304
+ if( apNew==0 ){
215305
+ pParse->rc = SQLITE_NOMEM;
215306
+ return SQLITE_NOMEM;
215307
+ }
215308
+ pParse->apPhrase = apNew;
215309
+ }
215310
+ return SQLITE_OK;
215311
+}
215172215312
215173215313
/*
215174215314
** This function is called by the parser to process a string token. The
215175215315
** string may or may not be quoted. In any case it is tokenized and a
215176215316
** phrase object consisting of all tokens returned.
@@ -215203,20 +215343,13 @@
215203215343
fts5ExprPhraseFree(sCtx.pPhrase);
215204215344
sCtx.pPhrase = 0;
215205215345
}else{
215206215346
215207215347
if( pAppend==0 ){
215208
- if( (pParse->nPhrase % 8)==0 ){
215209
- sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
215210
- Fts5ExprPhrase **apNew;
215211
- apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
215212
- if( apNew==0 ){
215213
- pParse->rc = SQLITE_NOMEM;
215214
- fts5ExprPhraseFree(sCtx.pPhrase);
215215
- return 0;
215216
- }
215217
- pParse->apPhrase = apNew;
215348
+ if( parseGrowPhraseArray(pParse) ){
215349
+ fts5ExprPhraseFree(sCtx.pPhrase);
215350
+ return 0;
215218215351
}
215219215352
pParse->nPhrase++;
215220215353
}
215221215354
215222215355
if( sCtx.pPhrase==0 ){
@@ -215618,10 +215751,71 @@
215618215751
sqlite3_free(pSub);
215619215752
}else{
215620215753
p->apChild[p->nChild++] = pSub;
215621215754
}
215622215755
}
215756
+
215757
+/*
215758
+** This function is used when parsing LIKE or GLOB patterns against
215759
+** trigram indexes that specify either detail=column or detail=none.
215760
+** It converts a phrase:
215761
+**
215762
+** abc + def + ghi
215763
+**
215764
+** into an AND tree:
215765
+**
215766
+** abc AND def AND ghi
215767
+*/
215768
+static Fts5ExprNode *fts5ParsePhraseToAnd(
215769
+ Fts5Parse *pParse,
215770
+ Fts5ExprNearset *pNear
215771
+){
215772
+ int nTerm = pNear->apPhrase[0]->nTerm;
215773
+ int ii;
215774
+ int nByte;
215775
+ Fts5ExprNode *pRet;
215776
+
215777
+ assert( pNear->nPhrase==1 );
215778
+ assert( pParse->bPhraseToAnd );
215779
+
215780
+ nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
215781
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215782
+ if( pRet ){
215783
+ pRet->eType = FTS5_AND;
215784
+ pRet->nChild = nTerm;
215785
+ fts5ExprAssignXNext(pRet);
215786
+ pParse->nPhrase--;
215787
+ for(ii=0; ii<nTerm; ii++){
215788
+ Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
215789
+ &pParse->rc, sizeof(Fts5ExprPhrase)
215790
+ );
215791
+ if( pPhrase ){
215792
+ if( parseGrowPhraseArray(pParse) ){
215793
+ fts5ExprPhraseFree(pPhrase);
215794
+ }else{
215795
+ pParse->apPhrase[pParse->nPhrase++] = pPhrase;
215796
+ pPhrase->nTerm = 1;
215797
+ pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
215798
+ &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
215799
+ );
215800
+ pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
215801
+ 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
215802
+ );
215803
+ }
215804
+ }
215805
+ }
215806
+
215807
+ if( pParse->rc ){
215808
+ sqlite3Fts5ParseNodeFree(pRet);
215809
+ pRet = 0;
215810
+ }else{
215811
+ sqlite3Fts5ParseNearsetFree(pNear);
215812
+ }
215813
+ }
215814
+
215815
+ return pRet;
215816
+}
215623215817
215624215818
/*
215625215819
** Allocate and return a new expression object. If anything goes wrong (i.e.
215626215820
** OOM error), leave an error code in pParse and return NULL.
215627215821
*/
@@ -215643,55 +215837,62 @@
215643215837
);
215644215838
if( eType==FTS5_STRING && pNear==0 ) return 0;
215645215839
if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
215646215840
if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
215647215841
215648
- if( eType==FTS5_NOT ){
215649
- nChild = 2;
215650
- }else if( eType==FTS5_AND || eType==FTS5_OR ){
215651
- nChild = 2;
215652
- if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
215653
- if( pRight->eType==eType ) nChild += pRight->nChild-1;
215654
- }
215655
-
215656
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
215657
- pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215658
-
215659
- if( pRet ){
215660
- pRet->eType = eType;
215661
- pRet->pNear = pNear;
215662
- fts5ExprAssignXNext(pRet);
215663
- if( eType==FTS5_STRING ){
215664
- int iPhrase;
215665
- for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
215666
- pNear->apPhrase[iPhrase]->pNode = pRet;
215667
- if( pNear->apPhrase[iPhrase]->nTerm==0 ){
215668
- pRet->xNext = 0;
215669
- pRet->eType = FTS5_EOF;
215670
- }
215671
- }
215672
-
215673
- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
215674
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
215675
- if( pNear->nPhrase!=1
215676
- || pPhrase->nTerm>1
215677
- || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
215678
- ){
215679
- assert( pParse->rc==SQLITE_OK );
215680
- pParse->rc = SQLITE_ERROR;
215681
- assert( pParse->zErr==0 );
215682
- pParse->zErr = sqlite3_mprintf(
215683
- "fts5: %s queries are not supported (detail!=full)",
215684
- pNear->nPhrase==1 ? "phrase": "NEAR"
215685
- );
215686
- sqlite3_free(pRet);
215687
- pRet = 0;
215688
- }
215689
- }
215690
- }else{
215691
- fts5ExprAddChildren(pRet, pLeft);
215692
- fts5ExprAddChildren(pRet, pRight);
215842
+ if( eType==FTS5_STRING
215843
+ && pParse->bPhraseToAnd
215844
+ && pNear->apPhrase[0]->nTerm>1
215845
+ ){
215846
+ pRet = fts5ParsePhraseToAnd(pParse, pNear);
215847
+ }else{
215848
+ if( eType==FTS5_NOT ){
215849
+ nChild = 2;
215850
+ }else if( eType==FTS5_AND || eType==FTS5_OR ){
215851
+ nChild = 2;
215852
+ if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
215853
+ if( pRight->eType==eType ) nChild += pRight->nChild-1;
215854
+ }
215855
+
215856
+ nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
215857
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215858
+
215859
+ if( pRet ){
215860
+ pRet->eType = eType;
215861
+ pRet->pNear = pNear;
215862
+ fts5ExprAssignXNext(pRet);
215863
+ if( eType==FTS5_STRING ){
215864
+ int iPhrase;
215865
+ for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
215866
+ pNear->apPhrase[iPhrase]->pNode = pRet;
215867
+ if( pNear->apPhrase[iPhrase]->nTerm==0 ){
215868
+ pRet->xNext = 0;
215869
+ pRet->eType = FTS5_EOF;
215870
+ }
215871
+ }
215872
+
215873
+ if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
215874
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
215875
+ if( pNear->nPhrase!=1
215876
+ || pPhrase->nTerm>1
215877
+ || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
215878
+ ){
215879
+ assert( pParse->rc==SQLITE_OK );
215880
+ pParse->rc = SQLITE_ERROR;
215881
+ assert( pParse->zErr==0 );
215882
+ pParse->zErr = sqlite3_mprintf(
215883
+ "fts5: %s queries are not supported (detail!=full)",
215884
+ pNear->nPhrase==1 ? "phrase": "NEAR"
215885
+ );
215886
+ sqlite3_free(pRet);
215887
+ pRet = 0;
215888
+ }
215889
+ }
215890
+ }else{
215891
+ fts5ExprAddChildren(pRet, pLeft);
215892
+ fts5ExprAddChildren(pRet, pRight);
215893
+ }
215693215894
}
215694215895
}
215695215896
}
215696215897
215697215898
if( pRet==0 ){
@@ -216041,11 +216242,11 @@
216041216242
zExpr = (const char*)sqlite3_value_text(apVal[0]);
216042216243
if( zExpr==0 ) zExpr = "";
216043216244
216044216245
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
216045216246
if( rc==SQLITE_OK ){
216046
- rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
216247
+ rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
216047216248
}
216048216249
if( rc==SQLITE_OK ){
216049216250
char *zText;
216050216251
if( pExpr->pRoot->xNext==0 ){
216051216252
zText = sqlite3_mprintf("");
@@ -216746,12 +216947,13 @@
216746216947
pPtr = (u8*)p;
216747216948
216748216949
/* If this is a new rowid, append the 4-byte size field for the previous
216749216950
** entry, and the new rowid for this entry. */
216750216951
if( iRowid!=p->iRowid ){
216952
+ u64 iDiff = (u64)iRowid - (u64)p->iRowid;
216751216953
fts5HashAddPoslistSize(pHash, p, 0);
216752
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
216954
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
216753216955
p->iRowid = iRowid;
216754216956
bNew = 1;
216755216957
p->iSzPoslist = p->nData;
216756216958
if( pHash->eDetail!=FTS5_DETAIL_NONE ){
216757216959
p->nData += 1;
@@ -218722,11 +218924,11 @@
218722218924
n = pIter->iEndofDoclist;
218723218925
}
218724218926
218725218927
ASSERT_SZLEAF_OK(pIter->pLeaf);
218726218928
while( 1 ){
218727
- i64 iDelta = 0;
218929
+ u64 iDelta = 0;
218728218930
218729218931
if( eDetail==FTS5_DETAIL_NONE ){
218730218932
/* todo */
218731218933
if( i<n && a[i]==0 ){
218732218934
i++;
@@ -218737,11 +218939,11 @@
218737218939
int bDummy;
218738218940
i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
218739218941
i += nPos;
218740218942
}
218741218943
if( i>=n ) break;
218742
- i += fts5GetVarint(&a[i], (u64*)&iDelta);
218944
+ i += fts5GetVarint(&a[i], &iDelta);
218743218945
pIter->iRowid += iDelta;
218744218946
218745218947
/* If necessary, grow the pIter->aRowidOffset[] array. */
218746218948
if( iRowidOffset>=pIter->nRowidOffset ){
218747218949
int nNew = pIter->nRowidOffset + 8;
@@ -218836,20 +219038,20 @@
218836219038
UNUSED_PARAM(pbUnused);
218837219039
218838219040
if( pIter->iRowidOffset>0 ){
218839219041
u8 *a = pIter->pLeaf->p;
218840219042
int iOff;
218841
- i64 iDelta;
219043
+ u64 iDelta;
218842219044
218843219045
pIter->iRowidOffset--;
218844219046
pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
218845219047
fts5SegIterLoadNPos(p, pIter);
218846219048
iOff = pIter->iLeafOffset;
218847219049
if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
218848219050
iOff += pIter->nPos;
218849219051
}
218850
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
219052
+ fts5GetVarint(&a[iOff], &iDelta);
218851219053
pIter->iRowid -= iDelta;
218852219054
}else{
218853219055
fts5SegIterReverseNewPage(p, pIter);
218854219056
}
218855219057
}
@@ -224064,10 +224266,27 @@
224064224266
{
224065224267
pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
224066224268
}
224067224269
#endif
224068224270
}
224271
+
224272
+static int fts5UsePatternMatch(
224273
+ Fts5Config *pConfig,
224274
+ struct sqlite3_index_constraint *p
224275
+){
224276
+ assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
224277
+ assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
224278
+ if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
224279
+ return 1;
224280
+ }
224281
+ if( pConfig->ePattern==FTS5_PATTERN_LIKE
224282
+ && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
224283
+ ){
224284
+ return 1;
224285
+ }
224286
+ return 0;
224287
+}
224069224288
224070224289
/*
224071224290
** Implementation of the xBestIndex method for FTS5 tables. Within the
224072224291
** WHERE constraint, it searches for the following:
224073224292
**
@@ -224094,11 +224313,13 @@
224094224313
** idxStr is used to encode data from the WHERE clause. For each argument
224095224314
** passed to the xFilter method, the following is appended to idxStr:
224096224315
**
224097224316
** Match against table column: "m"
224098224317
** Match against rank column: "r"
224099
-** Match against other column: "<column-number>"
224318
+** Match against other column: "M<column-number>"
224319
+** LIKE against other column: "L<column-number>"
224320
+** GLOB against other column: "G<column-number>"
224100224321
** Equality constraint against the rowid: "="
224101224322
** A < or <= against the rowid: "<"
224102224323
** A > or >= against the rowid: ">"
224103224324
**
224104224325
** This function ensures that there is at most one "r" or "=". And that if
@@ -224155,11 +224376,11 @@
224155224376
"recursively defined fts5 content table"
224156224377
);
224157224378
return SQLITE_ERROR;
224158224379
}
224159224380
224160
- idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
224381
+ idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
224161224382
if( idxStr==0 ) return SQLITE_NOMEM;
224162224383
pInfo->idxStr = idxStr;
224163224384
pInfo->needToFreeIdxStr = 1;
224164224385
224165224386
for(i=0; i<pInfo->nConstraint; i++){
@@ -224179,29 +224400,33 @@
224179224400
}else{
224180224401
if( iCol==nCol+1 ){
224181224402
if( bSeenRank ) continue;
224182224403
idxStr[iIdxStr++] = 'r';
224183224404
bSeenRank = 1;
224184
- }else{
224405
+ }else if( iCol>=0 ){
224185224406
bSeenMatch = 1;
224186
- idxStr[iIdxStr++] = 'm';
224187
- if( iCol<nCol ){
224188
- sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224189
- idxStr += strlen(&idxStr[iIdxStr]);
224190
- assert( idxStr[iIdxStr]=='\0' );
224191
- }
224407
+ idxStr[iIdxStr++] = 'M';
224408
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224409
+ idxStr += strlen(&idxStr[iIdxStr]);
224410
+ assert( idxStr[iIdxStr]=='\0' );
224192224411
}
224193224412
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224194224413
pInfo->aConstraintUsage[i].omit = 1;
224195224414
}
224196
- }
224197
- else if( p->usable && bSeenEq==0
224198
- && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
224199
- ){
224200
- idxStr[iIdxStr++] = '=';
224201
- bSeenEq = 1;
224202
- pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224415
+ }else if( p->usable ){
224416
+ if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
224417
+ assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
224418
+ idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
224419
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224420
+ idxStr += strlen(&idxStr[iIdxStr]);
224421
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224422
+ assert( idxStr[iIdxStr]=='\0' );
224423
+ }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
224424
+ idxStr[iIdxStr++] = '=';
224425
+ bSeenEq = 1;
224426
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224427
+ }
224203224428
}
224204224429
}
224205224430
224206224431
if( bSeenEq==0 ){
224207224432
for(i=0; i<pInfo->nConstraint; i++){
@@ -224830,41 +225055,55 @@
224830225055
for(i=0; i<nVal; i++){
224831225056
switch( idxStr[iIdxStr++] ){
224832225057
case 'r':
224833225058
pRank = apVal[i];
224834225059
break;
224835
- case 'm': {
225060
+ case 'M': {
224836225061
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
224837225062
if( zText==0 ) zText = "";
224838
-
224839
- if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
224840
- iCol = 0;
224841
- do{
224842
- iCol = iCol*10 + (idxStr[iIdxStr]-'0');
224843
- iIdxStr++;
224844
- }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
224845
- }else{
224846
- iCol = pConfig->nCol;
224847
- }
225063
+ iCol = 0;
225064
+ do{
225065
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
225066
+ iIdxStr++;
225067
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
224848225068
224849225069
if( zText[0]=='*' ){
224850225070
/* The user has issued a query of the form "MATCH '*...'". This
224851225071
** indicates that the MATCH expression is not a full text query,
224852225072
** but a request for an internal parameter. */
224853225073
rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
224854225074
goto filter_out;
224855225075
}else{
224856225076
char **pzErr = &pTab->p.base.zErrMsg;
224857
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
225077
+ rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
224858225078
if( rc==SQLITE_OK ){
224859225079
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
224860225080
pExpr = 0;
224861225081
}
224862225082
if( rc!=SQLITE_OK ) goto filter_out;
224863225083
}
224864225084
224865225085
break;
225086
+ }
225087
+ case 'L':
225088
+ case 'G': {
225089
+ int bGlob = (idxStr[iIdxStr-1]=='G');
225090
+ const char *zText = (const char*)sqlite3_value_text(apVal[i]);
225091
+ iCol = 0;
225092
+ do{
225093
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
225094
+ iIdxStr++;
225095
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
225096
+ if( zText ){
225097
+ rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
225098
+ }
225099
+ if( rc==SQLITE_OK ){
225100
+ rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
225101
+ pExpr = 0;
225102
+ }
225103
+ if( rc!=SQLITE_OK ) goto filter_out;
225104
+ break;
224866225105
}
224867225106
case '=':
224868225107
pRowidEq = apVal[i];
224869225108
break;
224870225109
case '<':
@@ -226273,12 +226512,11 @@
226273226512
226274226513
static int sqlite3Fts5GetTokenizer(
226275226514
Fts5Global *pGlobal,
226276226515
const char **azArg,
226277226516
int nArg,
226278
- Fts5Tokenizer **ppTok,
226279
- fts5_tokenizer **ppTokApi,
226517
+ Fts5Config *pConfig,
226280226518
char **pzErr
226281226519
){
226282226520
Fts5TokenizerModule *pMod;
226283226521
int rc = SQLITE_OK;
226284226522
@@ -226286,20 +226524,26 @@
226286226524
if( pMod==0 ){
226287226525
assert( nArg>0 );
226288226526
rc = SQLITE_ERROR;
226289226527
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
226290226528
}else{
226291
- rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
226292
- *ppTokApi = &pMod->x;
226293
- if( rc!=SQLITE_OK && pzErr ){
226294
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
226529
+ rc = pMod->x.xCreate(
226530
+ pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
226531
+ );
226532
+ pConfig->pTokApi = &pMod->x;
226533
+ if( rc!=SQLITE_OK ){
226534
+ if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
226535
+ }else{
226536
+ pConfig->ePattern = sqlite3Fts5TokenizerPattern(
226537
+ pMod->x.xCreate, pConfig->pTok
226538
+ );
226295226539
}
226296226540
}
226297226541
226298226542
if( rc!=SQLITE_OK ){
226299
- *ppTokApi = 0;
226300
- *ppTok = 0;
226543
+ pConfig->pTokApi = 0;
226544
+ pConfig->pTok = 0;
226301226545
}
226302226546
226303226547
return rc;
226304226548
}
226305226549
@@ -226344,11 +226588,11 @@
226344226588
int nArg, /* Number of args */
226345226589
sqlite3_value **apUnused /* Function arguments */
226346226590
){
226347226591
assert( nArg==0 );
226348226592
UNUSED_PARAM2(nArg, apUnused);
226349
- sqlite3_result_text(pCtx, "fts5: 2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5", -1, SQLITE_TRANSIENT);
226593
+ sqlite3_result_text(pCtx, "fts5: 2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5", -1, SQLITE_TRANSIENT);
226350226594
}
226351226595
226352226596
/*
226353226597
** Return true if zName is the extension on one of the shadow tables used
226354226598
** by this module.
@@ -228897,10 +229141,135 @@
228897229141
sCtx.aBuf = p->aBuf;
228898229142
return p->tokenizer.xTokenize(
228899229143
p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
228900229144
);
228901229145
}
229146
+
229147
+/**************************************************************************
229148
+** Start of trigram implementation.
229149
+*/
229150
+typedef struct TrigramTokenizer TrigramTokenizer;
229151
+struct TrigramTokenizer {
229152
+ int bFold; /* True to fold to lower-case */
229153
+};
229154
+
229155
+/*
229156
+** Free a trigram tokenizer.
229157
+*/
229158
+static void fts5TriDelete(Fts5Tokenizer *p){
229159
+ sqlite3_free(p);
229160
+}
229161
+
229162
+/*
229163
+** Allocate a trigram tokenizer.
229164
+*/
229165
+static int fts5TriCreate(
229166
+ void *pCtx,
229167
+ const char **azArg,
229168
+ int nArg,
229169
+ Fts5Tokenizer **ppOut
229170
+){
229171
+ int rc = SQLITE_OK;
229172
+ TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
229173
+ if( pNew==0 ){
229174
+ rc = SQLITE_NOMEM;
229175
+ }else{
229176
+ int i;
229177
+ pNew->bFold = 1;
229178
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
229179
+ const char *zArg = azArg[i+1];
229180
+ if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
229181
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
229182
+ rc = SQLITE_ERROR;
229183
+ }else{
229184
+ pNew->bFold = (zArg[0]=='0');
229185
+ }
229186
+ }else{
229187
+ rc = SQLITE_ERROR;
229188
+ }
229189
+ }
229190
+ if( rc!=SQLITE_OK ){
229191
+ fts5TriDelete((Fts5Tokenizer*)pNew);
229192
+ pNew = 0;
229193
+ }
229194
+ }
229195
+ *ppOut = (Fts5Tokenizer*)pNew;
229196
+ return rc;
229197
+}
229198
+
229199
+/*
229200
+** Trigram tokenizer tokenize routine.
229201
+*/
229202
+static int fts5TriTokenize(
229203
+ Fts5Tokenizer *pTok,
229204
+ void *pCtx,
229205
+ int flags,
229206
+ const char *pText, int nText,
229207
+ int (*xToken)(void*, int, const char*, int, int, int)
229208
+){
229209
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
229210
+ int rc = SQLITE_OK;
229211
+ char aBuf[32];
229212
+ const unsigned char *zIn = (const unsigned char*)pText;
229213
+ const unsigned char *zEof = &zIn[nText];
229214
+ u32 iCode;
229215
+
229216
+ while( 1 ){
229217
+ char *zOut = aBuf;
229218
+ int iStart = zIn - (const unsigned char*)pText;
229219
+ const unsigned char *zNext;
229220
+
229221
+ READ_UTF8(zIn, zEof, iCode);
229222
+ if( iCode==0 ) break;
229223
+ zNext = zIn;
229224
+ if( zIn<zEof ){
229225
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229226
+ WRITE_UTF8(zOut, iCode);
229227
+ READ_UTF8(zIn, zEof, iCode);
229228
+ if( iCode==0 ) break;
229229
+ }else{
229230
+ break;
229231
+ }
229232
+ if( zIn<zEof ){
229233
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229234
+ WRITE_UTF8(zOut, iCode);
229235
+ READ_UTF8(zIn, zEof, iCode);
229236
+ if( iCode==0 ) break;
229237
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229238
+ WRITE_UTF8(zOut, iCode);
229239
+ }else{
229240
+ break;
229241
+ }
229242
+ rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
229243
+ if( rc!=SQLITE_OK ) break;
229244
+ zIn = zNext;
229245
+ }
229246
+
229247
+ return rc;
229248
+}
229249
+
229250
+/*
229251
+** Argument xCreate is a pointer to a constructor function for a tokenizer.
229252
+** pTok is a tokenizer previously created using the same method. This function
229253
+** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
229254
+** indicating the style of pattern matching that the tokenizer can support.
229255
+** In practice, this is:
229256
+**
229257
+** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
229258
+** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
229259
+** all other tokenizers - FTS5_PATTERN_NONE
229260
+*/
229261
+static int sqlite3Fts5TokenizerPattern(
229262
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
229263
+ Fts5Tokenizer *pTok
229264
+){
229265
+ if( xCreate==fts5TriCreate ){
229266
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
229267
+ return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
229268
+ }
229269
+ return FTS5_PATTERN_NONE;
229270
+}
228902229271
228903229272
/*
228904229273
** Register all built-in tokenizers with FTS5.
228905229274
*/
228906229275
static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -228909,10 +229278,11 @@
228909229278
fts5_tokenizer x;
228910229279
} aBuiltin[] = {
228911229280
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
228912229281
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
228913229282
{ "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
229283
+ { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
228914229284
};
228915229285
228916229286
int rc = SQLITE_OK; /* Return code */
228917229287
int i; /* To iterate through builtin functions */
228918229288
@@ -231140,12 +231510,12 @@
231140231510
}
231141231511
#endif /* SQLITE_CORE */
231142231512
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
231143231513
231144231514
/************** End of stmt.c ************************************************/
231145
-#if __LINE__!=231145
231515
+#if __LINE__!=231515
231146231516
#undef SQLITE_SOURCE_ID
231147
-#define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c4alt2"
231517
+#define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca64alt2"
231148231518
#endif
231149231519
/* Return the source-id for this library */
231150231520
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
231151231521
/************************** End of sqlite3.c ******************************/
231152231522
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1171,11 +1171,11 @@
1171 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1172 ** [sqlite_version()] and [sqlite_source_id()].
1173 */
1174 #define SQLITE_VERSION "3.34.0"
1175 #define SQLITE_VERSION_NUMBER 3034000
1176 #define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"
1177
1178 /*
1179 ** CAPI3REF: Run-Time Library Version Numbers
1180 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1181 **
@@ -88945,11 +88945,12 @@
88945 **
88946 ** Begin a transaction on database P1 if a transaction is not already
88947 ** active.
88948 ** If P2 is non-zero, then a write-transaction is started, or if a
88949 ** read-transaction is already active, it is upgraded to a write-transaction.
88950 ** If P2 is zero, then a read-transaction is started.
 
88951 **
88952 ** P1 is the index of the database file on which the transaction is
88953 ** started. Index 0 is the main database file and index 1 is the
88954 ** file used for temporary tables. Indices of 2 or more are used for
88955 ** attached databases.
@@ -88979,10 +88980,11 @@
88979 Btree *pBt;
88980 int iMeta = 0;
88981
88982 assert( p->bIsReader );
88983 assert( p->readOnly==0 || pOp->p2==0 );
 
88984 assert( pOp->p1>=0 && pOp->p1<db->nDb );
88985 assert( DbMaskTest(p->btreeMask, pOp->p1) );
88986 if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
88987 rc = SQLITE_READONLY;
88988 goto abort_due_to_error;
@@ -89842,22 +89844,22 @@
89842 }
89843 break;
89844 }
89845
89846
89847 /* Opcode: SeekScan P1 * * * *
89848 ** Synopsis: Scan-ahead up to P1 rows
89849 **
89850 ** This opcode is a prefix opcode to OP_SeekGE. In other words, this
89851 ** opcode must be immediately followed by OP_SeekGE. Furthermore, the
89852 ** OP_SeekGE must be followed by OP_IdxGT. These constraints are
89853 ** checked by assert() statements.
89854 **
89855 ** This opcode uses the P1 through P4 operands of the subsequent
89856 ** OP_SeekGE. In the text that follows, the operands of the subsequent
89857 ** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
89858 ** the P1 operand of this opcode is used, and it is denoted as This.P1.
 
89859 **
89860 ** This opcode helps to optimize IN operators on a multi-column index
89861 ** where the IN operator is on the later terms of the index by avoiding
89862 ** unnecessary seeks on the btree, substituting steps to the next row
89863 ** of the b-tree instead. A correct answer is obtained if this opcode
@@ -89871,39 +89873,43 @@
89871 ** then this opcode is a no-op and control passes through into the OP_SeekGE.
89872 **
89873 ** If the SeekGE.P1 cursor is pointing to a valid row, then that row
89874 ** might be the target row, or it might be near and slightly before the
89875 ** target row. This opcode attempts to position the cursor on the target
89876 ** row by, perhaps stepping by invoking sqlite3BtreeStep() on the cursor
89877 ** between 0 and This.P1 times.
89878 **
89879 ** There are three possible outcomes from this opcode:<ol>
89880 **
89881 ** <li> If after This.P1 steps, the cursor is still point to a place that
89882 ** is earlier in the btree than the target row,
89883 ** then fall through into the subsquence OP_SeekGE opcode.
89884 **
89885 ** <li> If the cursor is successfully moved to the target row by 0 or more
89886 ** sqlite3BtreeNext() calls, then jump to the first instruction after the
89887 ** OP_IdxGT opcode - or in other words, skip the next two opcodes.
89888 **
89889 ** <li> If the cursor ends up past the target row (indicating the the target
89890 ** row does not exist in the btree) then jump to SeekOP.P2.
89891 ** </ol>
89892 */
89893 case OP_SeekScan: {
89894 VdbeCursor *pC;
89895 int res;
89896 int n;
89897 UnpackedRecord r;
89898
89899 assert( pOp[1].opcode==OP_SeekGE );
89900 assert( pOp[2].opcode==OP_IdxGT );
89901 assert( pOp[1].p1==pOp[2].p1 );
89902 assert( pOp[1].p2==pOp[2].p2 );
89903 assert( pOp[1].p3==pOp[2].p3 );
89904 assert( pOp[1].p4.i==pOp[2].p4.i );
 
 
 
 
89905 assert( pOp->p1>0 );
89906 pC = p->apCsr[pOp[1].p1];
89907 assert( pC!=0 );
89908 assert( pC->eCurType==CURTYPE_BTREE );
89909 assert( !pC->isTable );
@@ -89913,12 +89919,12 @@
89913 printf("... cursor not valid - fall through\n");
89914 }
89915 #endif
89916 break;
89917 }
89918 n = pOp->p1;
89919 assert( n>=1 );
89920 r.pKeyInfo = pC->pKeyInfo;
89921 r.nField = (u16)pOp[1].p4.i;
89922 r.default_rc = 0;
89923 r.aMem = &aMem[pOp[1].p3];
89924 #ifdef SQLITE_DEBUG
@@ -89936,37 +89942,37 @@
89936 if( rc ) goto abort_due_to_error;
89937 if( res>0 ){
89938 seekscan_search_fail:
89939 #ifdef SQLITE_DEBUG
89940 if( db->flags&SQLITE_VdbeTrace ){
89941 printf("... %d steps and then skip\n", pOp->p1 - n);
89942 }
89943 #endif
89944 VdbeBranchTaken(1,3);
89945 pOp++;
89946 goto jump_to_p2;
89947 }
89948 if( res==0 ){
89949 #ifdef SQLITE_DEBUG
89950 if( db->flags&SQLITE_VdbeTrace ){
89951 printf("... %d steps and then success\n", pOp->p1 - n);
89952 }
89953 #endif
89954 VdbeBranchTaken(2,3);
89955 pOp += 2;
89956 break;
89957 }
89958 if( n<=0 ){
89959 #ifdef SQLITE_DEBUG
89960 if( db->flags&SQLITE_VdbeTrace ){
89961 printf("... fall through after %d steps\n", pOp->p1);
89962 }
89963 #endif
89964 VdbeBranchTaken(0,3);
89965 break;
89966 }
89967 n--;
89968 rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
89969 if( rc ){
89970 if( rc==SQLITE_DONE ){
89971 rc = SQLITE_OK;
89972 goto seekscan_search_fail;
@@ -100066,11 +100072,13 @@
100066 ** SELECT * FROM t1 WHERE (select a from t1);
100067 */
100068 SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
100069 int op;
100070 while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
100071 assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
 
 
100072 pExpr = pExpr->pLeft;
100073 assert( pExpr!=0 );
100074 }
100075 op = pExpr->op;
100076 if( op==TK_SELECT ){
@@ -112360,11 +112368,11 @@
112360 Table *p;
112361 int i;
112362 char *zColl; /* Dequoted name of collation sequence */
112363 sqlite3 *db;
112364
112365 if( (p = pParse->pNewTable)==0 ) return;
112366 i = p->nCol-1;
112367 db = pParse->db;
112368 zColl = sqlite3NameFromToken(db, pToken);
112369 if( !zColl ) return;
112370
@@ -115361,11 +115369,20 @@
115361 }
115362 v = sqlite3GetVdbe(pParse);
115363 if( !v ) return;
115364 if( type!=TK_DEFERRED ){
115365 for(i=0; i<db->nDb; i++){
115366 sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
 
 
 
 
 
 
 
 
 
115367 sqlite3VdbeUsesBtree(v, i);
115368 }
115369 }
115370 sqlite3VdbeAddOp0(v, OP_AutoCommit);
115371 }
@@ -117348,14 +117365,10 @@
117348 ** opcode if it is present */
117349 sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
117350 }
117351 if( regOut ){
117352 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
117353 if( pIdx->pTable->pSelect ){
117354 const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
117355 sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
117356 }
117357 }
117358 sqlite3ReleaseTempRange(pParse, regBase, nCol);
117359 return regBase;
117360 }
117361
@@ -138158,11 +138171,11 @@
138158 pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
138159 }
138160 #endif
138161 pList = sqlite3ExprListAppend(pParse, pList, pNew);
138162 }
138163 eDest = SRT_Upfrom;
138164 }else if( pTab->pSelect ){
138165 for(i=0; i<pTab->nCol; i++){
138166 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
138167 }
138168 eDest = SRT_Table;
@@ -139111,16 +139124,30 @@
139111 ephemTab = pParse->nTab++;
139112 addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
139113 regArg = pParse->nMem + 1;
139114 pParse->nMem += nArg;
139115 if( pSrc->nSrc>1 ){
 
139116 Expr *pRow;
139117 ExprList *pList;
139118 if( pRowid ){
139119 pRow = sqlite3ExprDup(db, pRowid, 0);
 
 
 
 
139120 }else{
139121 pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
 
 
 
 
 
 
 
 
 
139122 }
139123 pList = sqlite3ExprListAppend(pParse, 0, pRow);
139124
139125 for(i=0; i<pTab->nCol; i++){
139126 if( aXRef[i]>=0 ){
@@ -139130,11 +139157,11 @@
139130 }else{
139131 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
139132 }
139133 }
139134
139135 updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
139136 sqlite3ExprListDelete(db, pList);
139137 eOnePass = ONEPASS_OFF;
139138 }else{
139139 regRec = ++pParse->nMem;
139140 regRowid = ++pParse->nMem;
@@ -142457,11 +142484,16 @@
142457 pIn->eEndLoopOp = OP_Noop;
142458 }
142459 pIn++;
142460 }
142461 }
142462 if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
 
 
 
 
 
142463 sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
142464 }
142465 }else{
142466 pLevel->u.in.nIn = 0;
142467 }
@@ -143507,10 +143539,11 @@
143507 char *zEndAff = 0; /* Affinity for end of range constraint */
143508 u8 bSeekPastNull = 0; /* True to seek past initial nulls */
143509 u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
143510 int omitTable; /* True if we use the index only */
143511 int regBignull = 0; /* big-null flag register */
 
143512
143513 pIdx = pLoop->u.btree.pIndex;
143514 iIdxCur = pLevel->iIdxCur;
143515 assert( nEq>=pLoop->nSkip );
143516
@@ -143652,22 +143685,22 @@
143652 VdbeComment((v, "NULL-scan pass ctr"));
143653 }
143654
143655 op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
143656 assert( op!=0 );
143657 if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
143658 assert( op==OP_SeekGE );
143659 assert( regBignull==0 );
143660 /* TUNING: The OP_SeekScan opcode seeks to reduce the number
143661 ** of expensive seek operations by replacing a single seek with
143662 ** 1 or more step operations. The question is, how many steps
143663 ** should we try before giving up and going with a seek. The cost
143664 ** of a seek is proportional to the logarithm of the of the number
143665 ** of entries in the tree, so basing the number of steps to try
143666 ** on the estimated number of rows in the btree seems like a good
143667 ** guess. */
143668 sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10);
 
143669 VdbeCoverage(v);
143670 }
143671 sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143672 VdbeCoverage(v);
143673 VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -143748,10 +143781,11 @@
143748 sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143749 testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
143750 testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
143751 testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
143752 testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
 
143753 }
143754 if( regBignull ){
143755 /* During a NULL-scan, check to see if we have reached the end of
143756 ** the NULLs */
143757 assert( bSeekPastNull==!bStopAtNull );
@@ -148484,11 +148518,11 @@
148484 }
148485 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
148486 /* "x IN (value, value, ...)" */
148487 nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
148488 }
148489 if( pProbe->hasStat1 ){
148490 LogEst M, logK, safetyMargin;
148491 /* Let:
148492 ** N = the total number of rows in the table
148493 ** K = the number of entries on the RHS of the IN operator
148494 ** M = the number of rows in the table that match terms to the
@@ -148503,11 +148537,12 @@
148503 **
148504 ** Our estimates for M, K, and N might be inaccurate, so we build in
148505 ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
148506 ** with the index, as using an index has better worst-case behavior.
148507 ** If we do not have real sqlite_stat1 data, always prefer to use
148508 ** the index.
 
148509 */
148510 M = pProbe->aiRowLogEst[saved_nEq];
148511 logK = estLog(nIn);
148512 safetyMargin = 10; /* TUNING: extra weight for indexed IN */
148513 if( M + logK + safetyMargin < nIn + rLogSize ){
@@ -209277,10 +209312,11 @@
209277 int eDetail; /* FTS5_DETAIL_XXX value */
209278 char *zContentExprlist;
209279 Fts5Tokenizer *pTok;
209280 fts5_tokenizer *pTokApi;
209281 int bLock; /* True when table is preparing statement */
 
209282
209283 /* Values loaded from the %_config table */
209284 int iCookie; /* Incremented when %_config is modified */
209285 int pgsz; /* Approximate page size used in %_data */
209286 int nAutomerge; /* 'automerge' setting */
@@ -209297,21 +209333,23 @@
209297 int bPrefixIndex; /* True to use prefix-indexes */
209298 #endif
209299 };
209300
209301 /* Current expected value of %_config table 'version' field */
209302 #define FTS5_CURRENT_VERSION 4
209303
209304 #define FTS5_CONTENT_NORMAL 0
209305 #define FTS5_CONTENT_NONE 1
209306 #define FTS5_CONTENT_EXTERNAL 2
209307
209308 #define FTS5_DETAIL_FULL 0
209309 #define FTS5_DETAIL_NONE 1
209310 #define FTS5_DETAIL_COLUMNS 2
209311
209312
 
 
209313
209314 static int sqlite3Fts5ConfigParse(
209315 Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
209316 );
209317 static void sqlite3Fts5ConfigFree(Fts5Config*);
@@ -209647,12 +209685,11 @@
209647
209648 static int sqlite3Fts5GetTokenizer(
209649 Fts5Global*,
209650 const char **azArg,
209651 int nArg,
209652 Fts5Tokenizer**,
209653 fts5_tokenizer**,
209654 char **pzErr
209655 );
209656
209657 static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
209658
@@ -209777,14 +209814,22 @@
209777 };
209778
209779 /* Parse a MATCH expression. */
209780 static int sqlite3Fts5ExprNew(
209781 Fts5Config *pConfig,
 
209782 int iCol, /* Column on LHS of MATCH operator */
209783 const char *zExpr,
209784 Fts5Expr **ppNew,
209785 char **pzErr
 
 
 
 
 
 
 
209786 );
209787
209788 /*
209789 ** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
209790 ** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
@@ -209890,10 +209935,14 @@
209890 /**************************************************************************
209891 ** Interface to code in fts5_tokenizer.c.
209892 */
209893
209894 static int sqlite3Fts5TokenizerInit(fts5_api*);
 
 
 
 
209895 /*
209896 ** End of interface to code in fts5_tokenizer.c.
209897 **************************************************************************/
209898
209899 /**************************************************************************
@@ -212869,11 +212918,11 @@
212869 if( p==0 ){
212870 *pzErr = sqlite3_mprintf("parse error in tokenize directive");
212871 rc = SQLITE_ERROR;
212872 }else{
212873 rc = sqlite3Fts5GetTokenizer(pGlobal,
212874 (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
212875 pzErr
212876 );
212877 }
212878 }
212879 }
@@ -212941,13 +212990,11 @@
212941 ** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
212942 ** code if an error occurs.
212943 */
212944 static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
212945 assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
212946 return sqlite3Fts5GetTokenizer(
212947 pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
212948 );
212949 }
212950
212951 /*
212952 ** Gobble up the first bareword or quoted word from the input buffer zIn.
212953 ** Return a pointer to the character immediately following the last in
@@ -213635,10 +213682,11 @@
213635 char *zErr;
213636 int rc;
213637 int nPhrase; /* Size of apPhrase array */
213638 Fts5ExprPhrase **apPhrase; /* Array of all phrases */
213639 Fts5ExprNode *pExpr; /* Result of a successful parse */
 
213640 };
213641
213642 static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
213643 va_list ap;
213644 va_start(ap, zFmt);
@@ -213723,10 +213771,11 @@
213723 static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
213724 static void fts5ParseFree(void *p){ sqlite3_free(p); }
213725
213726 static int sqlite3Fts5ExprNew(
213727 Fts5Config *pConfig, /* FTS5 Configuration */
 
213728 int iCol,
213729 const char *zExpr, /* Expression text */
213730 Fts5Expr **ppNew,
213731 char **pzErr
213732 ){
@@ -213738,10 +213787,11 @@
213738 Fts5Expr *pNew;
213739
213740 *ppNew = 0;
213741 *pzErr = 0;
213742 memset(&sParse, 0, sizeof(sParse));
 
213743 pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
213744 if( pEngine==0 ){ return SQLITE_NOMEM; }
213745 sParse.pConfig = pConfig;
213746
213747 do {
@@ -213780,10 +213830,11 @@
213780 }
213781 pNew->pIndex = 0;
213782 pNew->pConfig = pConfig;
213783 pNew->apExprPhrase = sParse.apPhrase;
213784 pNew->nPhrase = sParse.nPhrase;
 
213785 sParse.apPhrase = 0;
213786 }
213787 }else{
213788 sqlite3Fts5ParseNodeFree(sParse.pExpr);
213789 }
@@ -213790,10 +213841,85 @@
213790
213791 sqlite3_free(sParse.apPhrase);
213792 *pzErr = sParse.zErr;
213793 return sParse.rc;
213794 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213795
213796 /*
213797 ** Free the expression node object passed as the only argument.
213798 */
213799 static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -215167,10 +215293,24 @@
215167
215168 static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
215169 assert( pParse->pExpr==0 );
215170 pParse->pExpr = p;
215171 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215172
215173 /*
215174 ** This function is called by the parser to process a string token. The
215175 ** string may or may not be quoted. In any case it is tokenized and a
215176 ** phrase object consisting of all tokens returned.
@@ -215203,20 +215343,13 @@
215203 fts5ExprPhraseFree(sCtx.pPhrase);
215204 sCtx.pPhrase = 0;
215205 }else{
215206
215207 if( pAppend==0 ){
215208 if( (pParse->nPhrase % 8)==0 ){
215209 sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
215210 Fts5ExprPhrase **apNew;
215211 apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
215212 if( apNew==0 ){
215213 pParse->rc = SQLITE_NOMEM;
215214 fts5ExprPhraseFree(sCtx.pPhrase);
215215 return 0;
215216 }
215217 pParse->apPhrase = apNew;
215218 }
215219 pParse->nPhrase++;
215220 }
215221
215222 if( sCtx.pPhrase==0 ){
@@ -215618,10 +215751,71 @@
215618 sqlite3_free(pSub);
215619 }else{
215620 p->apChild[p->nChild++] = pSub;
215621 }
215622 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215623
215624 /*
215625 ** Allocate and return a new expression object. If anything goes wrong (i.e.
215626 ** OOM error), leave an error code in pParse and return NULL.
215627 */
@@ -215643,55 +215837,62 @@
215643 );
215644 if( eType==FTS5_STRING && pNear==0 ) return 0;
215645 if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
215646 if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
215647
215648 if( eType==FTS5_NOT ){
215649 nChild = 2;
215650 }else if( eType==FTS5_AND || eType==FTS5_OR ){
215651 nChild = 2;
215652 if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
215653 if( pRight->eType==eType ) nChild += pRight->nChild-1;
215654 }
215655
215656 nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
215657 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215658
215659 if( pRet ){
215660 pRet->eType = eType;
215661 pRet->pNear = pNear;
215662 fts5ExprAssignXNext(pRet);
215663 if( eType==FTS5_STRING ){
215664 int iPhrase;
215665 for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
215666 pNear->apPhrase[iPhrase]->pNode = pRet;
215667 if( pNear->apPhrase[iPhrase]->nTerm==0 ){
215668 pRet->xNext = 0;
215669 pRet->eType = FTS5_EOF;
215670 }
215671 }
215672
215673 if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
215674 Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
215675 if( pNear->nPhrase!=1
215676 || pPhrase->nTerm>1
215677 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
215678 ){
215679 assert( pParse->rc==SQLITE_OK );
215680 pParse->rc = SQLITE_ERROR;
215681 assert( pParse->zErr==0 );
215682 pParse->zErr = sqlite3_mprintf(
215683 "fts5: %s queries are not supported (detail!=full)",
215684 pNear->nPhrase==1 ? "phrase": "NEAR"
215685 );
215686 sqlite3_free(pRet);
215687 pRet = 0;
215688 }
215689 }
215690 }else{
215691 fts5ExprAddChildren(pRet, pLeft);
215692 fts5ExprAddChildren(pRet, pRight);
 
 
 
 
 
 
 
215693 }
215694 }
215695 }
215696
215697 if( pRet==0 ){
@@ -216041,11 +216242,11 @@
216041 zExpr = (const char*)sqlite3_value_text(apVal[0]);
216042 if( zExpr==0 ) zExpr = "";
216043
216044 rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
216045 if( rc==SQLITE_OK ){
216046 rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
216047 }
216048 if( rc==SQLITE_OK ){
216049 char *zText;
216050 if( pExpr->pRoot->xNext==0 ){
216051 zText = sqlite3_mprintf("");
@@ -216746,12 +216947,13 @@
216746 pPtr = (u8*)p;
216747
216748 /* If this is a new rowid, append the 4-byte size field for the previous
216749 ** entry, and the new rowid for this entry. */
216750 if( iRowid!=p->iRowid ){
 
216751 fts5HashAddPoslistSize(pHash, p, 0);
216752 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
216753 p->iRowid = iRowid;
216754 bNew = 1;
216755 p->iSzPoslist = p->nData;
216756 if( pHash->eDetail!=FTS5_DETAIL_NONE ){
216757 p->nData += 1;
@@ -218722,11 +218924,11 @@
218722 n = pIter->iEndofDoclist;
218723 }
218724
218725 ASSERT_SZLEAF_OK(pIter->pLeaf);
218726 while( 1 ){
218727 i64 iDelta = 0;
218728
218729 if( eDetail==FTS5_DETAIL_NONE ){
218730 /* todo */
218731 if( i<n && a[i]==0 ){
218732 i++;
@@ -218737,11 +218939,11 @@
218737 int bDummy;
218738 i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
218739 i += nPos;
218740 }
218741 if( i>=n ) break;
218742 i += fts5GetVarint(&a[i], (u64*)&iDelta);
218743 pIter->iRowid += iDelta;
218744
218745 /* If necessary, grow the pIter->aRowidOffset[] array. */
218746 if( iRowidOffset>=pIter->nRowidOffset ){
218747 int nNew = pIter->nRowidOffset + 8;
@@ -218836,20 +219038,20 @@
218836 UNUSED_PARAM(pbUnused);
218837
218838 if( pIter->iRowidOffset>0 ){
218839 u8 *a = pIter->pLeaf->p;
218840 int iOff;
218841 i64 iDelta;
218842
218843 pIter->iRowidOffset--;
218844 pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
218845 fts5SegIterLoadNPos(p, pIter);
218846 iOff = pIter->iLeafOffset;
218847 if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
218848 iOff += pIter->nPos;
218849 }
218850 fts5GetVarint(&a[iOff], (u64*)&iDelta);
218851 pIter->iRowid -= iDelta;
218852 }else{
218853 fts5SegIterReverseNewPage(p, pIter);
218854 }
218855 }
@@ -224064,10 +224266,27 @@
224064 {
224065 pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
224066 }
224067 #endif
224068 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224069
224070 /*
224071 ** Implementation of the xBestIndex method for FTS5 tables. Within the
224072 ** WHERE constraint, it searches for the following:
224073 **
@@ -224094,11 +224313,13 @@
224094 ** idxStr is used to encode data from the WHERE clause. For each argument
224095 ** passed to the xFilter method, the following is appended to idxStr:
224096 **
224097 ** Match against table column: "m"
224098 ** Match against rank column: "r"
224099 ** Match against other column: "<column-number>"
 
 
224100 ** Equality constraint against the rowid: "="
224101 ** A < or <= against the rowid: "<"
224102 ** A > or >= against the rowid: ">"
224103 **
224104 ** This function ensures that there is at most one "r" or "=". And that if
@@ -224155,11 +224376,11 @@
224155 "recursively defined fts5 content table"
224156 );
224157 return SQLITE_ERROR;
224158 }
224159
224160 idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
224161 if( idxStr==0 ) return SQLITE_NOMEM;
224162 pInfo->idxStr = idxStr;
224163 pInfo->needToFreeIdxStr = 1;
224164
224165 for(i=0; i<pInfo->nConstraint; i++){
@@ -224179,29 +224400,33 @@
224179 }else{
224180 if( iCol==nCol+1 ){
224181 if( bSeenRank ) continue;
224182 idxStr[iIdxStr++] = 'r';
224183 bSeenRank = 1;
224184 }else{
224185 bSeenMatch = 1;
224186 idxStr[iIdxStr++] = 'm';
224187 if( iCol<nCol ){
224188 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224189 idxStr += strlen(&idxStr[iIdxStr]);
224190 assert( idxStr[iIdxStr]=='\0' );
224191 }
224192 }
224193 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224194 pInfo->aConstraintUsage[i].omit = 1;
224195 }
224196 }
224197 else if( p->usable && bSeenEq==0
224198 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
224199 ){
224200 idxStr[iIdxStr++] = '=';
224201 bSeenEq = 1;
224202 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
 
 
 
 
 
 
224203 }
224204 }
224205
224206 if( bSeenEq==0 ){
224207 for(i=0; i<pInfo->nConstraint; i++){
@@ -224830,41 +225055,55 @@
224830 for(i=0; i<nVal; i++){
224831 switch( idxStr[iIdxStr++] ){
224832 case 'r':
224833 pRank = apVal[i];
224834 break;
224835 case 'm': {
224836 const char *zText = (const char*)sqlite3_value_text(apVal[i]);
224837 if( zText==0 ) zText = "";
224838
224839 if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
224840 iCol = 0;
224841 do{
224842 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
224843 iIdxStr++;
224844 }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
224845 }else{
224846 iCol = pConfig->nCol;
224847 }
224848
224849 if( zText[0]=='*' ){
224850 /* The user has issued a query of the form "MATCH '*...'". This
224851 ** indicates that the MATCH expression is not a full text query,
224852 ** but a request for an internal parameter. */
224853 rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
224854 goto filter_out;
224855 }else{
224856 char **pzErr = &pTab->p.base.zErrMsg;
224857 rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
224858 if( rc==SQLITE_OK ){
224859 rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
224860 pExpr = 0;
224861 }
224862 if( rc!=SQLITE_OK ) goto filter_out;
224863 }
224864
224865 break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224866 }
224867 case '=':
224868 pRowidEq = apVal[i];
224869 break;
224870 case '<':
@@ -226273,12 +226512,11 @@
226273
226274 static int sqlite3Fts5GetTokenizer(
226275 Fts5Global *pGlobal,
226276 const char **azArg,
226277 int nArg,
226278 Fts5Tokenizer **ppTok,
226279 fts5_tokenizer **ppTokApi,
226280 char **pzErr
226281 ){
226282 Fts5TokenizerModule *pMod;
226283 int rc = SQLITE_OK;
226284
@@ -226286,20 +226524,26 @@
226286 if( pMod==0 ){
226287 assert( nArg>0 );
226288 rc = SQLITE_ERROR;
226289 *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
226290 }else{
226291 rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
226292 *ppTokApi = &pMod->x;
226293 if( rc!=SQLITE_OK && pzErr ){
226294 *pzErr = sqlite3_mprintf("error in tokenizer constructor");
 
 
 
 
 
 
226295 }
226296 }
226297
226298 if( rc!=SQLITE_OK ){
226299 *ppTokApi = 0;
226300 *ppTok = 0;
226301 }
226302
226303 return rc;
226304 }
226305
@@ -226344,11 +226588,11 @@
226344 int nArg, /* Number of args */
226345 sqlite3_value **apUnused /* Function arguments */
226346 ){
226347 assert( nArg==0 );
226348 UNUSED_PARAM2(nArg, apUnused);
226349 sqlite3_result_text(pCtx, "fts5: 2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5", -1, SQLITE_TRANSIENT);
226350 }
226351
226352 /*
226353 ** Return true if zName is the extension on one of the shadow tables used
226354 ** by this module.
@@ -228897,10 +229141,135 @@
228897 sCtx.aBuf = p->aBuf;
228898 return p->tokenizer.xTokenize(
228899 p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
228900 );
228901 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228902
228903 /*
228904 ** Register all built-in tokenizers with FTS5.
228905 */
228906 static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -228909,10 +229278,11 @@
228909 fts5_tokenizer x;
228910 } aBuiltin[] = {
228911 { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
228912 { "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
228913 { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
 
228914 };
228915
228916 int rc = SQLITE_OK; /* Return code */
228917 int i; /* To iterate through builtin functions */
228918
@@ -231140,12 +231510,12 @@
231140 }
231141 #endif /* SQLITE_CORE */
231142 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
231143
231144 /************** End of stmt.c ************************************************/
231145 #if __LINE__!=231145
231146 #undef SQLITE_SOURCE_ID
231147 #define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c4alt2"
231148 #endif
231149 /* Return the source-id for this library */
231150 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
231151 /************************** End of sqlite3.c ******************************/
231152
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1171,11 +1171,11 @@
1171 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1172 ** [sqlite_version()] and [sqlite_source_id()].
1173 */
1174 #define SQLITE_VERSION "3.34.0"
1175 #define SQLITE_VERSION_NUMBER 3034000
1176 #define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"
1177
1178 /*
1179 ** CAPI3REF: Run-Time Library Version Numbers
1180 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1181 **
@@ -88945,11 +88945,12 @@
88945 **
88946 ** Begin a transaction on database P1 if a transaction is not already
88947 ** active.
88948 ** If P2 is non-zero, then a write-transaction is started, or if a
88949 ** read-transaction is already active, it is upgraded to a write-transaction.
88950 ** If P2 is zero, then a read-transaction is started. If P2 is 2 or more
88951 ** then an exclusive transaction is started.
88952 **
88953 ** P1 is the index of the database file on which the transaction is
88954 ** started. Index 0 is the main database file and index 1 is the
88955 ** file used for temporary tables. Indices of 2 or more are used for
88956 ** attached databases.
@@ -88979,10 +88980,11 @@
88980 Btree *pBt;
88981 int iMeta = 0;
88982
88983 assert( p->bIsReader );
88984 assert( p->readOnly==0 || pOp->p2==0 );
88985 assert( pOp->p2>=0 && pOp->p2<=2 );
88986 assert( pOp->p1>=0 && pOp->p1<db->nDb );
88987 assert( DbMaskTest(p->btreeMask, pOp->p1) );
88988 if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
88989 rc = SQLITE_READONLY;
88990 goto abort_due_to_error;
@@ -89842,22 +89844,22 @@
89844 }
89845 break;
89846 }
89847
89848
89849 /* Opcode: SeekScan P1 P2 * * *
89850 ** Synopsis: Scan-ahead up to P1 rows
89851 **
89852 ** This opcode is a prefix opcode to OP_SeekGE. In other words, this
89853 ** opcode must be immediately followed by OP_SeekGE. This constraint is
 
89854 ** checked by assert() statements.
89855 **
89856 ** This opcode uses the P1 through P4 operands of the subsequent
89857 ** OP_SeekGE. In the text that follows, the operands of the subsequent
89858 ** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
89859 ** the P1 and P2 operands of this opcode are also used, and are called
89860 ** This.P1 and This.P2.
89861 **
89862 ** This opcode helps to optimize IN operators on a multi-column index
89863 ** where the IN operator is on the later terms of the index by avoiding
89864 ** unnecessary seeks on the btree, substituting steps to the next row
89865 ** of the b-tree instead. A correct answer is obtained if this opcode
@@ -89871,39 +89873,43 @@
89873 ** then this opcode is a no-op and control passes through into the OP_SeekGE.
89874 **
89875 ** If the SeekGE.P1 cursor is pointing to a valid row, then that row
89876 ** might be the target row, or it might be near and slightly before the
89877 ** target row. This opcode attempts to position the cursor on the target
89878 ** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
89879 ** between 0 and This.P1 times.
89880 **
89881 ** There are three possible outcomes from this opcode:<ol>
89882 **
89883 ** <li> If after This.P1 steps, the cursor is still point to a place that
89884 ** is earlier in the btree than the target row,
89885 ** then fall through into the subsquence OP_SeekGE opcode.
89886 **
89887 ** <li> If the cursor is successfully moved to the target row by 0 or more
89888 ** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
89889 ** past the OP_IdxGT opcode that follows the OP_SeekGE.
89890 **
89891 ** <li> If the cursor ends up past the target row (indicating the the target
89892 ** row does not exist in the btree) then jump to SeekOP.P2.
89893 ** </ol>
89894 */
89895 case OP_SeekScan: {
89896 VdbeCursor *pC;
89897 int res;
89898 int nStep;
89899 UnpackedRecord r;
89900
89901 assert( pOp[1].opcode==OP_SeekGE );
89902
89903 /* pOp->p2 points to the first instruction past the OP_IdxGT that
89904 ** follows the OP_SeekGE. */
89905 assert( pOp->p2>=(int)(pOp-aOp)+2 );
89906 assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
89907 assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
89908 assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
89909 assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
89910
89911 assert( pOp->p1>0 );
89912 pC = p->apCsr[pOp[1].p1];
89913 assert( pC!=0 );
89914 assert( pC->eCurType==CURTYPE_BTREE );
89915 assert( !pC->isTable );
@@ -89913,12 +89919,12 @@
89919 printf("... cursor not valid - fall through\n");
89920 }
89921 #endif
89922 break;
89923 }
89924 nStep = pOp->p1;
89925 assert( nStep>=1 );
89926 r.pKeyInfo = pC->pKeyInfo;
89927 r.nField = (u16)pOp[1].p4.i;
89928 r.default_rc = 0;
89929 r.aMem = &aMem[pOp[1].p3];
89930 #ifdef SQLITE_DEBUG
@@ -89936,37 +89942,37 @@
89942 if( rc ) goto abort_due_to_error;
89943 if( res>0 ){
89944 seekscan_search_fail:
89945 #ifdef SQLITE_DEBUG
89946 if( db->flags&SQLITE_VdbeTrace ){
89947 printf("... %d steps and then skip\n", pOp->p1 - nStep);
89948 }
89949 #endif
89950 VdbeBranchTaken(1,3);
89951 pOp++;
89952 goto jump_to_p2;
89953 }
89954 if( res==0 ){
89955 #ifdef SQLITE_DEBUG
89956 if( db->flags&SQLITE_VdbeTrace ){
89957 printf("... %d steps and then success\n", pOp->p1 - nStep);
89958 }
89959 #endif
89960 VdbeBranchTaken(2,3);
89961 goto jump_to_p2;
89962 break;
89963 }
89964 if( nStep<=0 ){
89965 #ifdef SQLITE_DEBUG
89966 if( db->flags&SQLITE_VdbeTrace ){
89967 printf("... fall through after %d steps\n", pOp->p1);
89968 }
89969 #endif
89970 VdbeBranchTaken(0,3);
89971 break;
89972 }
89973 nStep--;
89974 rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
89975 if( rc ){
89976 if( rc==SQLITE_DONE ){
89977 rc = SQLITE_OK;
89978 goto seekscan_search_fail;
@@ -100066,11 +100072,13 @@
100072 ** SELECT * FROM t1 WHERE (select a from t1);
100073 */
100074 SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
100075 int op;
100076 while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
100077 assert( pExpr->op==TK_COLLATE
100078 || pExpr->op==TK_IF_NULL_ROW
100079 || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
100080 pExpr = pExpr->pLeft;
100081 assert( pExpr!=0 );
100082 }
100083 op = pExpr->op;
100084 if( op==TK_SELECT ){
@@ -112360,11 +112368,11 @@
112368 Table *p;
112369 int i;
112370 char *zColl; /* Dequoted name of collation sequence */
112371 sqlite3 *db;
112372
112373 if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
112374 i = p->nCol-1;
112375 db = pParse->db;
112376 zColl = sqlite3NameFromToken(db, pToken);
112377 if( !zColl ) return;
112378
@@ -115361,11 +115369,20 @@
115369 }
115370 v = sqlite3GetVdbe(pParse);
115371 if( !v ) return;
115372 if( type!=TK_DEFERRED ){
115373 for(i=0; i<db->nDb; i++){
115374 int eTxnType;
115375 Btree *pBt = db->aDb[i].pBt;
115376 if( pBt && sqlite3BtreeIsReadonly(pBt) ){
115377 eTxnType = 0; /* Read txn */
115378 }else if( type==TK_EXCLUSIVE ){
115379 eTxnType = 2; /* Exclusive txn */
115380 }else{
115381 eTxnType = 1; /* Write txn */
115382 }
115383 sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
115384 sqlite3VdbeUsesBtree(v, i);
115385 }
115386 }
115387 sqlite3VdbeAddOp0(v, OP_AutoCommit);
115388 }
@@ -117348,14 +117365,10 @@
117365 ** opcode if it is present */
117366 sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
117367 }
117368 if( regOut ){
117369 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
 
 
 
 
117370 }
117371 sqlite3ReleaseTempRange(pParse, regBase, nCol);
117372 return regBase;
117373 }
117374
@@ -138158,11 +138171,11 @@
138171 pGrp = sqlite3ExprListAppend(pParse, pGrp, sqlite3ExprDup(db, pNew, 0));
138172 }
138173 #endif
138174 pList = sqlite3ExprListAppend(pParse, pList, pNew);
138175 }
138176 eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
138177 }else if( pTab->pSelect ){
138178 for(i=0; i<pTab->nCol; i++){
138179 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
138180 }
138181 eDest = SRT_Table;
@@ -139111,16 +139124,30 @@
139124 ephemTab = pParse->nTab++;
139125 addr= sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, nArg);
139126 regArg = pParse->nMem + 1;
139127 pParse->nMem += nArg;
139128 if( pSrc->nSrc>1 ){
139129 Index *pPk = 0;
139130 Expr *pRow;
139131 ExprList *pList;
139132 if( HasRowid(pTab) ){
139133 if( pRowid ){
139134 pRow = sqlite3ExprDup(db, pRowid, 0);
139135 }else{
139136 pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
139137 }
139138 }else{
139139 i16 iPk; /* PRIMARY KEY column */
139140 pPk = sqlite3PrimaryKeyIndex(pTab);
139141 assert( pPk!=0 );
139142 assert( pPk->nKeyCol==1 );
139143 iPk = pPk->aiColumn[0];
139144 if( aXRef[iPk]>=0 ){
139145 pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
139146 }else{
139147 pRow = exprRowColumn(pParse, iPk);
139148 }
139149 }
139150 pList = sqlite3ExprListAppend(pParse, 0, pRow);
139151
139152 for(i=0; i<pTab->nCol; i++){
139153 if( aXRef[i]>=0 ){
@@ -139130,11 +139157,11 @@
139157 }else{
139158 pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
139159 }
139160 }
139161
139162 updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
139163 sqlite3ExprListDelete(db, pList);
139164 eOnePass = ONEPASS_OFF;
139165 }else{
139166 regRec = ++pParse->nMem;
139167 regRowid = ++pParse->nMem;
@@ -142457,11 +142484,16 @@
142484 pIn->eEndLoopOp = OP_Noop;
142485 }
142486 pIn++;
142487 }
142488 }
142489 testcase( iEq>0
142490 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
142491 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
142492 if( iEq>0
142493 && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
142494 ){
142495 sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
142496 }
142497 }else{
142498 pLevel->u.in.nIn = 0;
142499 }
@@ -143507,10 +143539,11 @@
143539 char *zEndAff = 0; /* Affinity for end of range constraint */
143540 u8 bSeekPastNull = 0; /* True to seek past initial nulls */
143541 u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
143542 int omitTable; /* True if we use the index only */
143543 int regBignull = 0; /* big-null flag register */
143544 int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
143545
143546 pIdx = pLoop->u.btree.pIndex;
143547 iIdxCur = pLevel->iIdxCur;
143548 assert( nEq>=pLoop->nSkip );
143549
@@ -143652,22 +143685,22 @@
143685 VdbeComment((v, "NULL-scan pass ctr"));
143686 }
143687
143688 op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
143689 assert( op!=0 );
143690 if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
 
143691 assert( regBignull==0 );
143692 /* TUNING: The OP_SeekScan opcode seeks to reduce the number
143693 ** of expensive seek operations by replacing a single seek with
143694 ** 1 or more step operations. The question is, how many steps
143695 ** should we try before giving up and going with a seek. The cost
143696 ** of a seek is proportional to the logarithm of the of the number
143697 ** of entries in the tree, so basing the number of steps to try
143698 ** on the estimated number of rows in the btree seems like a good
143699 ** guess. */
143700 addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
143701 (pIdx->aiRowLogEst[0]+9)/10);
143702 VdbeCoverage(v);
143703 }
143704 sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143705 VdbeCoverage(v);
143706 VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -143748,10 +143781,11 @@
143781 sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
143782 testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
143783 testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
143784 testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
143785 testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
143786 if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
143787 }
143788 if( regBignull ){
143789 /* During a NULL-scan, check to see if we have reached the end of
143790 ** the NULLs */
143791 assert( bSeekPastNull==!bStopAtNull );
@@ -148484,11 +148518,11 @@
148518 }
148519 }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
148520 /* "x IN (value, value, ...)" */
148521 nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
148522 }
148523 if( pProbe->hasStat1 && rLogSize>=10 ){
148524 LogEst M, logK, safetyMargin;
148525 /* Let:
148526 ** N = the total number of rows in the table
148527 ** K = the number of entries on the RHS of the IN operator
148528 ** M = the number of rows in the table that match terms to the
@@ -148503,11 +148537,12 @@
148537 **
148538 ** Our estimates for M, K, and N might be inaccurate, so we build in
148539 ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
148540 ** with the index, as using an index has better worst-case behavior.
148541 ** If we do not have real sqlite_stat1 data, always prefer to use
148542 ** the index. Do not bother with this optimization on very small
148543 ** tables (less than 2 rows) as it is pointless in that case.
148544 */
148545 M = pProbe->aiRowLogEst[saved_nEq];
148546 logK = estLog(nIn);
148547 safetyMargin = 10; /* TUNING: extra weight for indexed IN */
148548 if( M + logK + safetyMargin < nIn + rLogSize ){
@@ -209277,10 +209312,11 @@
209312 int eDetail; /* FTS5_DETAIL_XXX value */
209313 char *zContentExprlist;
209314 Fts5Tokenizer *pTok;
209315 fts5_tokenizer *pTokApi;
209316 int bLock; /* True when table is preparing statement */
209317 int ePattern; /* FTS_PATTERN_XXX constant */
209318
209319 /* Values loaded from the %_config table */
209320 int iCookie; /* Incremented when %_config is modified */
209321 int pgsz; /* Approximate page size used in %_data */
209322 int nAutomerge; /* 'automerge' setting */
@@ -209297,21 +209333,23 @@
209333 int bPrefixIndex; /* True to use prefix-indexes */
209334 #endif
209335 };
209336
209337 /* Current expected value of %_config table 'version' field */
209338 #define FTS5_CURRENT_VERSION 4
209339
209340 #define FTS5_CONTENT_NORMAL 0
209341 #define FTS5_CONTENT_NONE 1
209342 #define FTS5_CONTENT_EXTERNAL 2
209343
209344 #define FTS5_DETAIL_FULL 0
209345 #define FTS5_DETAIL_NONE 1
209346 #define FTS5_DETAIL_COLUMNS 2
209347
209348 #define FTS5_PATTERN_NONE 0
209349 #define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
209350 #define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */
209351
209352 static int sqlite3Fts5ConfigParse(
209353 Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
209354 );
209355 static void sqlite3Fts5ConfigFree(Fts5Config*);
@@ -209647,12 +209685,11 @@
209685
209686 static int sqlite3Fts5GetTokenizer(
209687 Fts5Global*,
209688 const char **azArg,
209689 int nArg,
209690 Fts5Config*,
 
209691 char **pzErr
209692 );
209693
209694 static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
209695
@@ -209777,14 +209814,22 @@
209814 };
209815
209816 /* Parse a MATCH expression. */
209817 static int sqlite3Fts5ExprNew(
209818 Fts5Config *pConfig,
209819 int bPhraseToAnd,
209820 int iCol, /* Column on LHS of MATCH operator */
209821 const char *zExpr,
209822 Fts5Expr **ppNew,
209823 char **pzErr
209824 );
209825 static int sqlite3Fts5ExprPattern(
209826 Fts5Config *pConfig,
209827 int bGlob,
209828 int iCol,
209829 const char *zText,
209830 Fts5Expr **pp
209831 );
209832
209833 /*
209834 ** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
209835 ** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr);
@@ -209890,10 +209935,14 @@
209935 /**************************************************************************
209936 ** Interface to code in fts5_tokenizer.c.
209937 */
209938
209939 static int sqlite3Fts5TokenizerInit(fts5_api*);
209940 static int sqlite3Fts5TokenizerPattern(
209941 int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
209942 Fts5Tokenizer *pTok
209943 );
209944 /*
209945 ** End of interface to code in fts5_tokenizer.c.
209946 **************************************************************************/
209947
209948 /**************************************************************************
@@ -212869,11 +212918,11 @@
212918 if( p==0 ){
212919 *pzErr = sqlite3_mprintf("parse error in tokenize directive");
212920 rc = SQLITE_ERROR;
212921 }else{
212922 rc = sqlite3Fts5GetTokenizer(pGlobal,
212923 (const char**)azArg, (int)nArg, pConfig,
212924 pzErr
212925 );
212926 }
212927 }
212928 }
@@ -212941,13 +212990,11 @@
212990 ** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
212991 ** code if an error occurs.
212992 */
212993 static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
212994 assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
212995 return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
 
 
212996 }
212997
212998 /*
212999 ** Gobble up the first bareword or quoted word from the input buffer zIn.
213000 ** Return a pointer to the character immediately following the last in
@@ -213635,10 +213682,11 @@
213682 char *zErr;
213683 int rc;
213684 int nPhrase; /* Size of apPhrase array */
213685 Fts5ExprPhrase **apPhrase; /* Array of all phrases */
213686 Fts5ExprNode *pExpr; /* Result of a successful parse */
213687 int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
213688 };
213689
213690 static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
213691 va_list ap;
213692 va_start(ap, zFmt);
@@ -213723,10 +213771,11 @@
213771 static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
213772 static void fts5ParseFree(void *p){ sqlite3_free(p); }
213773
213774 static int sqlite3Fts5ExprNew(
213775 Fts5Config *pConfig, /* FTS5 Configuration */
213776 int bPhraseToAnd,
213777 int iCol,
213778 const char *zExpr, /* Expression text */
213779 Fts5Expr **ppNew,
213780 char **pzErr
213781 ){
@@ -213738,10 +213787,11 @@
213787 Fts5Expr *pNew;
213788
213789 *ppNew = 0;
213790 *pzErr = 0;
213791 memset(&sParse, 0, sizeof(sParse));
213792 sParse.bPhraseToAnd = bPhraseToAnd;
213793 pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
213794 if( pEngine==0 ){ return SQLITE_NOMEM; }
213795 sParse.pConfig = pConfig;
213796
213797 do {
@@ -213780,10 +213830,11 @@
213830 }
213831 pNew->pIndex = 0;
213832 pNew->pConfig = pConfig;
213833 pNew->apExprPhrase = sParse.apPhrase;
213834 pNew->nPhrase = sParse.nPhrase;
213835 pNew->bDesc = 0;
213836 sParse.apPhrase = 0;
213837 }
213838 }else{
213839 sqlite3Fts5ParseNodeFree(sParse.pExpr);
213840 }
@@ -213790,10 +213841,85 @@
213841
213842 sqlite3_free(sParse.apPhrase);
213843 *pzErr = sParse.zErr;
213844 return sParse.rc;
213845 }
213846
213847 /*
213848 ** This function is only called when using the special 'trigram' tokenizer.
213849 ** Argument zText contains the text of a LIKE or GLOB pattern matched
213850 ** against column iCol. This function creates and compiles an FTS5 MATCH
213851 ** expression that will match a superset of the rows matched by the LIKE or
213852 ** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
213853 ** code.
213854 */
213855 static int sqlite3Fts5ExprPattern(
213856 Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
213857 ){
213858 i64 nText = strlen(zText);
213859 char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
213860 int rc = SQLITE_OK;
213861
213862 if( zExpr==0 ){
213863 rc = SQLITE_NOMEM;
213864 }else{
213865 char aSpec[3];
213866 int iOut = 0;
213867 int i = 0;
213868 int iFirst = 0;
213869
213870 if( bGlob==0 ){
213871 aSpec[0] = '_';
213872 aSpec[1] = '%';
213873 aSpec[2] = 0;
213874 }else{
213875 aSpec[0] = '*';
213876 aSpec[1] = '?';
213877 aSpec[2] = '[';
213878 }
213879
213880 while( i<=nText ){
213881 if( i==nText
213882 || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
213883 ){
213884 if( i-iFirst>=3 ){
213885 int jj;
213886 zExpr[iOut++] = '"';
213887 for(jj=iFirst; jj<i; jj++){
213888 zExpr[iOut++] = zText[jj];
213889 if( zText[jj]=='"' ) zExpr[iOut++] = '"';
213890 }
213891 zExpr[iOut++] = '"';
213892 zExpr[iOut++] = ' ';
213893 }
213894 if( zText[i]==aSpec[2] ){
213895 i += 2;
213896 if( zText[i-1]=='^' ) i++;
213897 while( i<nText && zText[i]!=']' ) i++;
213898 }
213899 iFirst = i+1;
213900 }
213901 i++;
213902 }
213903 if( iOut>0 ){
213904 int bAnd = 0;
213905 if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
213906 bAnd = 1;
213907 if( pConfig->eDetail==FTS5_DETAIL_NONE ){
213908 iCol = pConfig->nCol;
213909 }
213910 }
213911 zExpr[iOut] = '\0';
213912 rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
213913 }else{
213914 *pp = 0;
213915 }
213916 sqlite3_free(zExpr);
213917 }
213918
213919 return rc;
213920 }
213921
213922 /*
213923 ** Free the expression node object passed as the only argument.
213924 */
213925 static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -215167,10 +215293,24 @@
215293
215294 static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
215295 assert( pParse->pExpr==0 );
215296 pParse->pExpr = p;
215297 }
215298
215299 static int parseGrowPhraseArray(Fts5Parse *pParse){
215300 if( (pParse->nPhrase % 8)==0 ){
215301 sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
215302 Fts5ExprPhrase **apNew;
215303 apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
215304 if( apNew==0 ){
215305 pParse->rc = SQLITE_NOMEM;
215306 return SQLITE_NOMEM;
215307 }
215308 pParse->apPhrase = apNew;
215309 }
215310 return SQLITE_OK;
215311 }
215312
215313 /*
215314 ** This function is called by the parser to process a string token. The
215315 ** string may or may not be quoted. In any case it is tokenized and a
215316 ** phrase object consisting of all tokens returned.
@@ -215203,20 +215343,13 @@
215343 fts5ExprPhraseFree(sCtx.pPhrase);
215344 sCtx.pPhrase = 0;
215345 }else{
215346
215347 if( pAppend==0 ){
215348 if( parseGrowPhraseArray(pParse) ){
215349 fts5ExprPhraseFree(sCtx.pPhrase);
215350 return 0;
 
 
 
 
 
 
 
215351 }
215352 pParse->nPhrase++;
215353 }
215354
215355 if( sCtx.pPhrase==0 ){
@@ -215618,10 +215751,71 @@
215751 sqlite3_free(pSub);
215752 }else{
215753 p->apChild[p->nChild++] = pSub;
215754 }
215755 }
215756
215757 /*
215758 ** This function is used when parsing LIKE or GLOB patterns against
215759 ** trigram indexes that specify either detail=column or detail=none.
215760 ** It converts a phrase:
215761 **
215762 ** abc + def + ghi
215763 **
215764 ** into an AND tree:
215765 **
215766 ** abc AND def AND ghi
215767 */
215768 static Fts5ExprNode *fts5ParsePhraseToAnd(
215769 Fts5Parse *pParse,
215770 Fts5ExprNearset *pNear
215771 ){
215772 int nTerm = pNear->apPhrase[0]->nTerm;
215773 int ii;
215774 int nByte;
215775 Fts5ExprNode *pRet;
215776
215777 assert( pNear->nPhrase==1 );
215778 assert( pParse->bPhraseToAnd );
215779
215780 nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
215781 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215782 if( pRet ){
215783 pRet->eType = FTS5_AND;
215784 pRet->nChild = nTerm;
215785 fts5ExprAssignXNext(pRet);
215786 pParse->nPhrase--;
215787 for(ii=0; ii<nTerm; ii++){
215788 Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
215789 &pParse->rc, sizeof(Fts5ExprPhrase)
215790 );
215791 if( pPhrase ){
215792 if( parseGrowPhraseArray(pParse) ){
215793 fts5ExprPhraseFree(pPhrase);
215794 }else{
215795 pParse->apPhrase[pParse->nPhrase++] = pPhrase;
215796 pPhrase->nTerm = 1;
215797 pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
215798 &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
215799 );
215800 pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
215801 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
215802 );
215803 }
215804 }
215805 }
215806
215807 if( pParse->rc ){
215808 sqlite3Fts5ParseNodeFree(pRet);
215809 pRet = 0;
215810 }else{
215811 sqlite3Fts5ParseNearsetFree(pNear);
215812 }
215813 }
215814
215815 return pRet;
215816 }
215817
215818 /*
215819 ** Allocate and return a new expression object. If anything goes wrong (i.e.
215820 ** OOM error), leave an error code in pParse and return NULL.
215821 */
@@ -215643,55 +215837,62 @@
215837 );
215838 if( eType==FTS5_STRING && pNear==0 ) return 0;
215839 if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
215840 if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
215841
215842 if( eType==FTS5_STRING
215843 && pParse->bPhraseToAnd
215844 && pNear->apPhrase[0]->nTerm>1
215845 ){
215846 pRet = fts5ParsePhraseToAnd(pParse, pNear);
215847 }else{
215848 if( eType==FTS5_NOT ){
215849 nChild = 2;
215850 }else if( eType==FTS5_AND || eType==FTS5_OR ){
215851 nChild = 2;
215852 if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
215853 if( pRight->eType==eType ) nChild += pRight->nChild-1;
215854 }
215855
215856 nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
215857 pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
215858
215859 if( pRet ){
215860 pRet->eType = eType;
215861 pRet->pNear = pNear;
215862 fts5ExprAssignXNext(pRet);
215863 if( eType==FTS5_STRING ){
215864 int iPhrase;
215865 for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
215866 pNear->apPhrase[iPhrase]->pNode = pRet;
215867 if( pNear->apPhrase[iPhrase]->nTerm==0 ){
215868 pRet->xNext = 0;
215869 pRet->eType = FTS5_EOF;
215870 }
215871 }
215872
215873 if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
215874 Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
215875 if( pNear->nPhrase!=1
215876 || pPhrase->nTerm>1
215877 || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
215878 ){
215879 assert( pParse->rc==SQLITE_OK );
215880 pParse->rc = SQLITE_ERROR;
215881 assert( pParse->zErr==0 );
215882 pParse->zErr = sqlite3_mprintf(
215883 "fts5: %s queries are not supported (detail!=full)",
215884 pNear->nPhrase==1 ? "phrase": "NEAR"
215885 );
215886 sqlite3_free(pRet);
215887 pRet = 0;
215888 }
215889 }
215890 }else{
215891 fts5ExprAddChildren(pRet, pLeft);
215892 fts5ExprAddChildren(pRet, pRight);
215893 }
215894 }
215895 }
215896 }
215897
215898 if( pRet==0 ){
@@ -216041,11 +216242,11 @@
216242 zExpr = (const char*)sqlite3_value_text(apVal[0]);
216243 if( zExpr==0 ) zExpr = "";
216244
216245 rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
216246 if( rc==SQLITE_OK ){
216247 rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
216248 }
216249 if( rc==SQLITE_OK ){
216250 char *zText;
216251 if( pExpr->pRoot->xNext==0 ){
216252 zText = sqlite3_mprintf("");
@@ -216746,12 +216947,13 @@
216947 pPtr = (u8*)p;
216948
216949 /* If this is a new rowid, append the 4-byte size field for the previous
216950 ** entry, and the new rowid for this entry. */
216951 if( iRowid!=p->iRowid ){
216952 u64 iDiff = (u64)iRowid - (u64)p->iRowid;
216953 fts5HashAddPoslistSize(pHash, p, 0);
216954 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
216955 p->iRowid = iRowid;
216956 bNew = 1;
216957 p->iSzPoslist = p->nData;
216958 if( pHash->eDetail!=FTS5_DETAIL_NONE ){
216959 p->nData += 1;
@@ -218722,11 +218924,11 @@
218924 n = pIter->iEndofDoclist;
218925 }
218926
218927 ASSERT_SZLEAF_OK(pIter->pLeaf);
218928 while( 1 ){
218929 u64 iDelta = 0;
218930
218931 if( eDetail==FTS5_DETAIL_NONE ){
218932 /* todo */
218933 if( i<n && a[i]==0 ){
218934 i++;
@@ -218737,11 +218939,11 @@
218939 int bDummy;
218940 i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
218941 i += nPos;
218942 }
218943 if( i>=n ) break;
218944 i += fts5GetVarint(&a[i], &iDelta);
218945 pIter->iRowid += iDelta;
218946
218947 /* If necessary, grow the pIter->aRowidOffset[] array. */
218948 if( iRowidOffset>=pIter->nRowidOffset ){
218949 int nNew = pIter->nRowidOffset + 8;
@@ -218836,20 +219038,20 @@
219038 UNUSED_PARAM(pbUnused);
219039
219040 if( pIter->iRowidOffset>0 ){
219041 u8 *a = pIter->pLeaf->p;
219042 int iOff;
219043 u64 iDelta;
219044
219045 pIter->iRowidOffset--;
219046 pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
219047 fts5SegIterLoadNPos(p, pIter);
219048 iOff = pIter->iLeafOffset;
219049 if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
219050 iOff += pIter->nPos;
219051 }
219052 fts5GetVarint(&a[iOff], &iDelta);
219053 pIter->iRowid -= iDelta;
219054 }else{
219055 fts5SegIterReverseNewPage(p, pIter);
219056 }
219057 }
@@ -224064,10 +224266,27 @@
224266 {
224267 pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
224268 }
224269 #endif
224270 }
224271
224272 static int fts5UsePatternMatch(
224273 Fts5Config *pConfig,
224274 struct sqlite3_index_constraint *p
224275 ){
224276 assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
224277 assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
224278 if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
224279 return 1;
224280 }
224281 if( pConfig->ePattern==FTS5_PATTERN_LIKE
224282 && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
224283 ){
224284 return 1;
224285 }
224286 return 0;
224287 }
224288
224289 /*
224290 ** Implementation of the xBestIndex method for FTS5 tables. Within the
224291 ** WHERE constraint, it searches for the following:
224292 **
@@ -224094,11 +224313,13 @@
224313 ** idxStr is used to encode data from the WHERE clause. For each argument
224314 ** passed to the xFilter method, the following is appended to idxStr:
224315 **
224316 ** Match against table column: "m"
224317 ** Match against rank column: "r"
224318 ** Match against other column: "M<column-number>"
224319 ** LIKE against other column: "L<column-number>"
224320 ** GLOB against other column: "G<column-number>"
224321 ** Equality constraint against the rowid: "="
224322 ** A < or <= against the rowid: "<"
224323 ** A > or >= against the rowid: ">"
224324 **
224325 ** This function ensures that there is at most one "r" or "=". And that if
@@ -224155,11 +224376,11 @@
224376 "recursively defined fts5 content table"
224377 );
224378 return SQLITE_ERROR;
224379 }
224380
224381 idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
224382 if( idxStr==0 ) return SQLITE_NOMEM;
224383 pInfo->idxStr = idxStr;
224384 pInfo->needToFreeIdxStr = 1;
224385
224386 for(i=0; i<pInfo->nConstraint; i++){
@@ -224179,29 +224400,33 @@
224400 }else{
224401 if( iCol==nCol+1 ){
224402 if( bSeenRank ) continue;
224403 idxStr[iIdxStr++] = 'r';
224404 bSeenRank = 1;
224405 }else if( iCol>=0 ){
224406 bSeenMatch = 1;
224407 idxStr[iIdxStr++] = 'M';
224408 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224409 idxStr += strlen(&idxStr[iIdxStr]);
224410 assert( idxStr[iIdxStr]=='\0' );
 
 
224411 }
224412 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224413 pInfo->aConstraintUsage[i].omit = 1;
224414 }
224415 }else if( p->usable ){
224416 if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
224417 assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
224418 idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
224419 sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
224420 idxStr += strlen(&idxStr[iIdxStr]);
224421 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224422 assert( idxStr[iIdxStr]=='\0' );
224423 }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
224424 idxStr[iIdxStr++] = '=';
224425 bSeenEq = 1;
224426 pInfo->aConstraintUsage[i].argvIndex = ++iCons;
224427 }
224428 }
224429 }
224430
224431 if( bSeenEq==0 ){
224432 for(i=0; i<pInfo->nConstraint; i++){
@@ -224830,41 +225055,55 @@
225055 for(i=0; i<nVal; i++){
225056 switch( idxStr[iIdxStr++] ){
225057 case 'r':
225058 pRank = apVal[i];
225059 break;
225060 case 'M': {
225061 const char *zText = (const char*)sqlite3_value_text(apVal[i]);
225062 if( zText==0 ) zText = "";
225063 iCol = 0;
225064 do{
225065 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
225066 iIdxStr++;
225067 }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
 
 
 
 
 
225068
225069 if( zText[0]=='*' ){
225070 /* The user has issued a query of the form "MATCH '*...'". This
225071 ** indicates that the MATCH expression is not a full text query,
225072 ** but a request for an internal parameter. */
225073 rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
225074 goto filter_out;
225075 }else{
225076 char **pzErr = &pTab->p.base.zErrMsg;
225077 rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
225078 if( rc==SQLITE_OK ){
225079 rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
225080 pExpr = 0;
225081 }
225082 if( rc!=SQLITE_OK ) goto filter_out;
225083 }
225084
225085 break;
225086 }
225087 case 'L':
225088 case 'G': {
225089 int bGlob = (idxStr[iIdxStr-1]=='G');
225090 const char *zText = (const char*)sqlite3_value_text(apVal[i]);
225091 iCol = 0;
225092 do{
225093 iCol = iCol*10 + (idxStr[iIdxStr]-'0');
225094 iIdxStr++;
225095 }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
225096 if( zText ){
225097 rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
225098 }
225099 if( rc==SQLITE_OK ){
225100 rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
225101 pExpr = 0;
225102 }
225103 if( rc!=SQLITE_OK ) goto filter_out;
225104 break;
225105 }
225106 case '=':
225107 pRowidEq = apVal[i];
225108 break;
225109 case '<':
@@ -226273,12 +226512,11 @@
226512
226513 static int sqlite3Fts5GetTokenizer(
226514 Fts5Global *pGlobal,
226515 const char **azArg,
226516 int nArg,
226517 Fts5Config *pConfig,
 
226518 char **pzErr
226519 ){
226520 Fts5TokenizerModule *pMod;
226521 int rc = SQLITE_OK;
226522
@@ -226286,20 +226524,26 @@
226524 if( pMod==0 ){
226525 assert( nArg>0 );
226526 rc = SQLITE_ERROR;
226527 *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
226528 }else{
226529 rc = pMod->x.xCreate(
226530 pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
226531 );
226532 pConfig->pTokApi = &pMod->x;
226533 if( rc!=SQLITE_OK ){
226534 if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
226535 }else{
226536 pConfig->ePattern = sqlite3Fts5TokenizerPattern(
226537 pMod->x.xCreate, pConfig->pTok
226538 );
226539 }
226540 }
226541
226542 if( rc!=SQLITE_OK ){
226543 pConfig->pTokApi = 0;
226544 pConfig->pTok = 0;
226545 }
226546
226547 return rc;
226548 }
226549
@@ -226344,11 +226588,11 @@
226588 int nArg, /* Number of args */
226589 sqlite3_value **apUnused /* Function arguments */
226590 ){
226591 assert( nArg==0 );
226592 UNUSED_PARAM2(nArg, apUnused);
226593 sqlite3_result_text(pCtx, "fts5: 2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5", -1, SQLITE_TRANSIENT);
226594 }
226595
226596 /*
226597 ** Return true if zName is the extension on one of the shadow tables used
226598 ** by this module.
@@ -228897,10 +229141,135 @@
229141 sCtx.aBuf = p->aBuf;
229142 return p->tokenizer.xTokenize(
229143 p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb
229144 );
229145 }
229146
229147 /**************************************************************************
229148 ** Start of trigram implementation.
229149 */
229150 typedef struct TrigramTokenizer TrigramTokenizer;
229151 struct TrigramTokenizer {
229152 int bFold; /* True to fold to lower-case */
229153 };
229154
229155 /*
229156 ** Free a trigram tokenizer.
229157 */
229158 static void fts5TriDelete(Fts5Tokenizer *p){
229159 sqlite3_free(p);
229160 }
229161
229162 /*
229163 ** Allocate a trigram tokenizer.
229164 */
229165 static int fts5TriCreate(
229166 void *pCtx,
229167 const char **azArg,
229168 int nArg,
229169 Fts5Tokenizer **ppOut
229170 ){
229171 int rc = SQLITE_OK;
229172 TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
229173 if( pNew==0 ){
229174 rc = SQLITE_NOMEM;
229175 }else{
229176 int i;
229177 pNew->bFold = 1;
229178 for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
229179 const char *zArg = azArg[i+1];
229180 if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
229181 if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
229182 rc = SQLITE_ERROR;
229183 }else{
229184 pNew->bFold = (zArg[0]=='0');
229185 }
229186 }else{
229187 rc = SQLITE_ERROR;
229188 }
229189 }
229190 if( rc!=SQLITE_OK ){
229191 fts5TriDelete((Fts5Tokenizer*)pNew);
229192 pNew = 0;
229193 }
229194 }
229195 *ppOut = (Fts5Tokenizer*)pNew;
229196 return rc;
229197 }
229198
229199 /*
229200 ** Trigram tokenizer tokenize routine.
229201 */
229202 static int fts5TriTokenize(
229203 Fts5Tokenizer *pTok,
229204 void *pCtx,
229205 int flags,
229206 const char *pText, int nText,
229207 int (*xToken)(void*, int, const char*, int, int, int)
229208 ){
229209 TrigramTokenizer *p = (TrigramTokenizer*)pTok;
229210 int rc = SQLITE_OK;
229211 char aBuf[32];
229212 const unsigned char *zIn = (const unsigned char*)pText;
229213 const unsigned char *zEof = &zIn[nText];
229214 u32 iCode;
229215
229216 while( 1 ){
229217 char *zOut = aBuf;
229218 int iStart = zIn - (const unsigned char*)pText;
229219 const unsigned char *zNext;
229220
229221 READ_UTF8(zIn, zEof, iCode);
229222 if( iCode==0 ) break;
229223 zNext = zIn;
229224 if( zIn<zEof ){
229225 if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229226 WRITE_UTF8(zOut, iCode);
229227 READ_UTF8(zIn, zEof, iCode);
229228 if( iCode==0 ) break;
229229 }else{
229230 break;
229231 }
229232 if( zIn<zEof ){
229233 if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229234 WRITE_UTF8(zOut, iCode);
229235 READ_UTF8(zIn, zEof, iCode);
229236 if( iCode==0 ) break;
229237 if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
229238 WRITE_UTF8(zOut, iCode);
229239 }else{
229240 break;
229241 }
229242 rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
229243 if( rc!=SQLITE_OK ) break;
229244 zIn = zNext;
229245 }
229246
229247 return rc;
229248 }
229249
229250 /*
229251 ** Argument xCreate is a pointer to a constructor function for a tokenizer.
229252 ** pTok is a tokenizer previously created using the same method. This function
229253 ** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
229254 ** indicating the style of pattern matching that the tokenizer can support.
229255 ** In practice, this is:
229256 **
229257 ** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
229258 ** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
229259 ** all other tokenizers - FTS5_PATTERN_NONE
229260 */
229261 static int sqlite3Fts5TokenizerPattern(
229262 int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
229263 Fts5Tokenizer *pTok
229264 ){
229265 if( xCreate==fts5TriCreate ){
229266 TrigramTokenizer *p = (TrigramTokenizer*)pTok;
229267 return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
229268 }
229269 return FTS5_PATTERN_NONE;
229270 }
229271
229272 /*
229273 ** Register all built-in tokenizers with FTS5.
229274 */
229275 static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
@@ -228909,10 +229278,11 @@
229278 fts5_tokenizer x;
229279 } aBuiltin[] = {
229280 { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
229281 { "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
229282 { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
229283 { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
229284 };
229285
229286 int rc = SQLITE_OK; /* Return code */
229287 int i; /* To iterate through builtin functions */
229288
@@ -231140,12 +231510,12 @@
231510 }
231511 #endif /* SQLITE_CORE */
231512 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
231513
231514 /************** End of stmt.c ************************************************/
231515 #if __LINE__!=231515
231516 #undef SQLITE_SOURCE_ID
231517 #define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca64alt2"
231518 #endif
231519 /* Return the source-id for this library */
231520 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
231521 /************************** End of sqlite3.c ******************************/
231522
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123123
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124124
** [sqlite_version()] and [sqlite_source_id()].
125125
*/
126126
#define SQLITE_VERSION "3.34.0"
127127
#define SQLITE_VERSION_NUMBER 3034000
128
-#define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"
128
+#define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"
129129
130130
/*
131131
** CAPI3REF: Run-Time Library Version Numbers
132132
** KEYWORDS: sqlite3_version sqlite3_sourceid
133133
**
134134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.34.0"
127 #define SQLITE_VERSION_NUMBER 3034000
128 #define SQLITE_SOURCE_ID "2020-09-30 18:06:51 4a43430fd23f88352c33b29c4c105b72f6dc821f94bf362040c41a1648c402e5"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.34.0"
127 #define SQLITE_VERSION_NUMBER 3034000
128 #define SQLITE_SOURCE_ID "2020-10-12 18:09:16 7e17c2f4b7dc9b563d0b4da949bb134dc7c4fc9c86ce03891432a884ca6409d5"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button