Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merged in trunk and resolved numerous code clashes in /chat. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | markdown-tagrefs |
| Files: | files | file ages | folders |
| SHA3-256: |
54dba7479043bdbd47184f6e59505666 |
| User & Date: | stephan 2021-12-16 04:20:53.731 |
Context
|
2021-12-31
| ||
| 02:59 | Merged in trunk. ... (check-in: c800d2ca82 user: stephan tags: markdown-tagrefs) | |
|
2021-12-16
| ||
| 04:20 | Merged in trunk and resolved numerous code clashes in /chat. ... (check-in: 54dba74790 user: stephan tags: markdown-tagrefs) | |
|
2021-12-14
| ||
| 14:49 | Added help text doc for -k alias for --keep for the open command, per [forum:6f17cf142f80e2c3 | forum post 6f17cf142f80e2c3]. ... (check-in: 8fee91d408 user: stephan tags: trunk) | |
|
2021-10-06
| ||
| 02:38 | Merge in trunk for test server deployment. ... (check-in: 664b04b280 user: stephan tags: markdown-tagrefs) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.18 |
Changes to auto.def.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 |
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
| | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
no-opt=0 => {Build without optimization}
json=0 => {Build with fossil JSON API enabled}
}
# Update the minimum required SQLite version number here, and also
# in src/main.c near the sqlite3_libversion_number() call. Take care
# that both places agree!
define MINIMUM_SQLITE_VERSION "3.37.0"
# This is useful for people wanting Fossil to use an external SQLite library
# to compare the one they have against the minimum required
if {[opt-bool print-minimum-sqlite-version]} {
puts [get-define MINIMUM_SQLITE_VERSION]
exit 0
}
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
2316 2317 2318 2319 2320 2321 2322 |
struct tm *pTm;
time_t now = time(0);
pTm = gmtime(&now);
if( pTm==0 ){
return mprintf("");
}else{
return mprintf("%04d-%02d-%02d %02d:%02d:%02d",
| | > > > > > > > > > > | 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 |
struct tm *pTm;
time_t now = time(0);
pTm = gmtime(&now);
if( pTm==0 ){
return mprintf("");
}else{
return mprintf("%04d-%02d-%02d %02d:%02d:%02d",
pTm->tm_year+1900, pTm->tm_mon+1, pTm->tm_mday,
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
}
}
/*
** COMMAND: test-date
**
** Show the current date and time in both RFC822 and ISO8601.
*/
void test_date(void){
fossil_print("%z = ", cgi_iso8601_datestamp());
fossil_print("%z\n", cgi_rfc822_datestamp(time(0)));
}
/*
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the
** most popular one (the one generated by cgi_rfc822_datestamp(), actually).
|
| ︙ | ︙ |
Changes to src/chat.c.
| ︙ | ︙ | |||
172 173 174 175 176 177 178 |
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
zInputPlaceholder0 =
mprintf("Type markdown-formatted message for %h.", zProjectName);
style_set_current_feature("chat");
style_header("Chat");
@ <div id='chat-input-area'>
| | > > > > > > > > | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
zInputPlaceholder0 =
mprintf("Type markdown-formatted message for %h.", zProjectName);
style_set_current_feature("chat");
style_header("Chat");
@ <div id='chat-input-area'>
@ <div id='chat-input-line-wrapper' class='compact'>
@ <input type="text" id="chat-input-field-single" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field"></input>
@ <textarea id="chat-input-field-multi" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field hidden"></textarea>
@ <div contenteditable id="chat-input-field-x" \
@ data-placeholder0="%h(zInputPlaceholder0)" \
@ data-placeholder="%h(zInputPlaceholder0)" \
@ class="chat-input-field hidden"></div>
@ <div id='chat-buttons-wrapper'>
@ <span class='cbutton' id="chat-button-preview" \
@ title="Preview message (Shift-Enter)">👁</span>
@ <span class='cbutton' id="chat-button-attach" \
@ title="Attach file to message">%s(zPaperclip)</span>
@ <span class='cbutton' id="chat-button-settings" \
@ title="Configure chat">⚙</span>
|
| ︙ | ︙ | |||
343 344 345 346 347 348 349 350 351 352 353 354 355 |
** to be entered into the chat history.
**
** On success it responds with an empty response: the new message
** should be fetched via /chat-poll. On error, e.g. login expiry,
** it emits a JSON response in the same form as described for
** /chat-poll errors, but as a standalone object instead of a
** list of objects.
*/
void chat_send_webpage(void){
int nByte;
const char *zMsg;
const char *zUserName;
login_check_credentials();
| > > > > > > > > > > > > | | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
** to be entered into the chat history.
**
** On success it responds with an empty response: the new message
** should be fetched via /chat-poll. On error, e.g. login expiry,
** it emits a JSON response in the same form as described for
** /chat-poll errors, but as a standalone object instead of a
** list of objects.
**
** Requests to this page should be POST, not GET. POST parameters
** include:
**
** msg The (Markdown) text of the message to be sent
**
** file The content of the file attachment
**
** lmtime ISO-8601 formatted date-time string showing the local time
** of the sender.
**
** At least one of the "msg" or "file" POST parameters must be provided.
*/
void chat_send_webpage(void){
int nByte;
const char *zMsg;
const char *zUserName;
login_check_credentials();
if( 0==g.perm.Chat ) {
chat_emit_permissions_error(0);
return;
}
chat_create_tables();
zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
nByte = atoi(PD("file:bytes","0"));
zMsg = PD("msg","");
|
| ︙ | ︙ | |||
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
** Invoking fetch("chat-delete/"+msgid) from javascript in the client
** will delete a chat entry from the CHAT table.
**
** This routine both deletes the identified chat entry and also inserts
** a new entry with the current timestamp and with:
**
** * xmsg = NULL
** * file = NULL
** * mdel = The msgid of the row that was deleted
**
** This new entry will then be propagated to all listeners so that they
** will know to delete their copies of the message too.
*/
void chat_delete_webpage(void){
int mdel;
| > > | 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 |
** Invoking fetch("chat-delete/"+msgid) from javascript in the client
** will delete a chat entry from the CHAT table.
**
** This routine both deletes the identified chat entry and also inserts
** a new entry with the current timestamp and with:
**
** * xmsg = NULL
**
** * file = NULL
**
** * mdel = The msgid of the row that was deleted
**
** This new entry will then be propagated to all listeners so that they
** will know to delete their copies of the message too.
*/
void chat_delete_webpage(void){
int mdel;
|
| ︙ | ︙ | |||
795 796 797 798 799 800 801 | ** This command performs actions associated with the /chat instance ** on the default remote Fossil repository (the Fossil repository whose ** URL shows when you run the "fossil remote" command) or to the URL ** specified by the --remote option. If there is no default remote ** Fossil repository and the --remote option is omitted, then this ** command fails with an error. ** | > > > > | | | | | < < > > > > > | 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 |
** This command performs actions associated with the /chat instance
** on the default remote Fossil repository (the Fossil repository whose
** URL shows when you run the "fossil remote" command) or to the URL
** specified by the --remote option. If there is no default remote
** Fossil repository and the --remote option is omitted, then this
** command fails with an error.
**
** Subcommands:
**
** > fossil chat
**
** When there is no SUBCOMMAND (when this command is simply "fossil chat")
** the response is to bring up a web-browser window to the chatroom
** on the default system web-browser. You can accomplish the same by
** typing the appropriate URL into the web-browser yourself. This
** command is merely a convenience for command-line oriented people.
**
** > fossil chat send [ARGUMENTS]
**
** This command sends a new message to the chatroom. The message
** to be sent is determined by arguments as follows:
**
** -f|--file FILENAME File to attach to the message
** -m|--message TEXT Text of the chat message
** --remote URL Send to this remote URL
** --unsafe Allow the use of unencrypted http://
**
** > fossil chat url
**
** Show the default URL used to access the chat server.
**
** Additional subcommands may be added in the future.
*/
void chat_command(void){
const char *zUrl = find_option("remote",0,1);
int urlFlags = 0;
int isDefaultUrl = 0;
int i;
|
| ︙ | ︙ | |||
939 940 941 942 943 944 945 |
}else{
fossil_print("ERROR: %s\n", blob_str(&down));
}
fossil_fatal("unable to send the chat message");
}
blob_reset(&down);
}else if( strcmp(g.argv[2],"url")==0 ){
| | | 968 969 970 971 972 973 974 975 976 977 978 979 980 |
}else{
fossil_print("ERROR: %s\n", blob_str(&down));
}
fossil_fatal("unable to send the chat message");
}
blob_reset(&down);
}else if( strcmp(g.argv[2],"url")==0 ){
/* Show the URL to access chat. */
fossil_print("%s/chat\n", zUrl);
}else{
fossil_fatal("no such subcommand \"%s\". Use --help for help", g.argv[2]);
}
}
|
Changes to src/checkin.c.
| ︙ | ︙ | |||
1347 1348 1349 1350 1351 1352 1353 |
'#'
);
diff_options(&DCfg, 0, 1);
DCfg.diffFlags |= DIFF_VERBOSE;
if( g.aCommitFile ){
FileDirList *diffFiles;
int i;
| > | | | | 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 |
'#'
);
diff_options(&DCfg, 0, 1);
DCfg.diffFlags |= DIFF_VERBOSE;
if( g.aCommitFile ){
FileDirList *diffFiles;
int i;
for(i=0; g.aCommitFile[i]!=0; ++i){}
diffFiles = fossil_malloc_zero((i+1) * sizeof(*diffFiles));
for(i=0; g.aCommitFile[i]!=0; ++i){
diffFiles[i].zName = db_text(0,
"SELECT pathname FROM vfile WHERE id=%d", g.aCommitFile[i]);
if( fossil_strcmp(diffFiles[i].zName, "." )==0 ){
diffFiles[0].zName[0] = '.';
diffFiles[0].zName[1] = 0;
break;
}
diffFiles[i].nName = strlen(diffFiles[i].zName);
diffFiles[i].nUsed = 0;
}
diff_against_disk(0, &DCfg, diffFiles, &prompt);
for( i=0; diffFiles[i].zName; ++i ){
fossil_free(diffFiles[i].zName);
}
fossil_free(diffFiles);
}else{
diff_against_disk(0, &DCfg, 0, &prompt);
}
|
| ︙ | ︙ | |||
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 |
** ("auto" lets Fossil choose it automatically,
** even for private branches)
** --close close the branch being committed
** --date-override DATETIME DATE to use instead of 'now'
** --delta use a delta manifest in the commit process
** --hash verify file status using hashing rather
** than relying on file mtimes
** --integrate close all merged-in branches
** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment
** -M|--message-file FILE read the commit comment from given file
** --mimetype MIMETYPE mimetype of check-in comment
** -n|--dry-run If given, display instead of run actions
** -v|--verbose Show a diff in the commit message prompt
** --no-prompt This option disables prompting the user for
| > > > > | 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 |
** ("auto" lets Fossil choose it automatically,
** even for private branches)
** --close close the branch being committed
** --date-override DATETIME DATE to use instead of 'now'
** --delta use a delta manifest in the commit process
** --hash verify file status using hashing rather
** than relying on file mtimes
** --ignore-clock-skew If a clock skew is detected, ignore it and
** behave as if the user had entered 'yes' to
** the question of whether to proceed despite
** the skew.
** --integrate close all merged-in branches
** -m|--comment COMMENT-TEXT use COMMENT-TEXT as commit comment
** -M|--message-file FILE read the commit comment from given file
** --mimetype MIMETYPE mimetype of check-in comment
** -n|--dry-run If given, display instead of run actions
** -v|--verbose Show a diff in the commit message prompt
** --no-prompt This option disables prompting the user for
|
| ︙ | ︙ | |||
2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 |
int szB; /* Size of the baseline manifest */
int nConflict = 0; /* Number of unresolved merge conflicts */
int abortCommit = 0; /* Abort the commit due to text format conversions */
Blob ans; /* Answer to continuation prompts */
char cReply; /* First character of ans */
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
memset(&sCiInfo, 0, sizeof(sCiInfo));
url_proxy_options();
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
noSign = find_option("nosign",0,0)!=0;
privateFlag = find_option("private",0,0)!=0;
| > | 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 |
int szB; /* Size of the baseline manifest */
int nConflict = 0; /* Number of unresolved merge conflicts */
int abortCommit = 0; /* Abort the commit due to text format conversions */
Blob ans; /* Answer to continuation prompts */
char cReply; /* First character of ans */
int bRecheck = 0; /* Repeat fork and closed-branch checks*/
int bAutoBrClr = 0; /* Value of "--branchcolor" is "auto" */
int bIgnoreSkew = 0; /* --ignore-clock-skew flag */
memset(&sCiInfo, 0, sizeof(sCiInfo));
url_proxy_options();
/* --sha1sum is an undocumented alias for --hash for backwards compatiblity */
useHash = find_option("hash",0,0)!=0 || find_option("sha1sum",0,0)!=0;
noSign = find_option("nosign",0,0)!=0;
privateFlag = find_option("private",0,0)!=0;
|
| ︙ | ︙ | |||
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 |
zComFile = find_option("message-file", "M", 1);
sCiInfo.zDateOvrd = find_option("date-override",0,1);
sCiInfo.zUserOvrd = find_option("user-override",0,1);
db_must_be_within_tree();
noSign = db_get_boolean("omitsign", 0)|noSign;
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
useCksum = db_get_boolean("repo-cksum", 1);
outputManifest = db_get_manifest_setting();
verify_all_options();
/* Get the ID of the parent manifest artifact */
vid = db_lget_int("checkout", 0);
if( vid==0 ){
useCksum = 1;
| > | 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 |
zComFile = find_option("message-file", "M", 1);
sCiInfo.zDateOvrd = find_option("date-override",0,1);
sCiInfo.zUserOvrd = find_option("user-override",0,1);
db_must_be_within_tree();
noSign = db_get_boolean("omitsign", 0)|noSign;
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
useCksum = db_get_boolean("repo-cksum", 1);
bIgnoreSkew = find_option("ignore-clock-skew",0,0)!=0;
outputManifest = db_get_manifest_setting();
verify_all_options();
/* Get the ID of the parent manifest artifact */
vid = db_lget_int("checkout", 0);
if( vid==0 ){
useCksum = 1;
|
| ︙ | ︙ | |||
2344 2345 2346 2347 2348 2349 2350 |
}
/* Require confirmation to continue with the check-in if there is
** clock skew
*/
if( g.clockSkewSeen ){
| > > > | | 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 |
}
/* Require confirmation to continue with the check-in if there is
** clock skew
*/
if( g.clockSkewSeen ){
if( bIgnoreSkew!=0 ){
cReply = 'y';
fossil_warning("Clock skew ignored due to --ignore-clock-skew.");
}else if( !noPrompt ){
prompt_user("continue in spite of time skew (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
blob_reset(&ans);
}else{
fossil_print("Abandoning commit due to time skew\n");
cReply = 'N';
}
|
| ︙ | ︙ |
Changes to src/clone.c.
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
}
db_begin_transaction();
if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
fossil_fatal("there are unresolved deltas -"
" the clone is probably incomplete and unusable.");
}
fossil_print("Rebuilding repository meta-data...\n");
| | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
}
db_begin_transaction();
if( db_exists("SELECT 1 FROM delta WHERE srcId IN phantom") ){
fossil_fatal("there are unresolved deltas -"
" the clone is probably incomplete and unusable.");
}
fossil_print("Rebuilding repository meta-data...\n");
rebuild_db(1, 0);
if( !noCompress ){
fossil_print("Extra delta compression... "); fflush(stdout);
extra_deltification();
fossil_print("\n");
}
db_end_transaction(0);
fossil_print("Vacuuming the database... "); fflush(stdout);
|
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
Blob cmd;
fossil_print("opening the new %s repository in directory %s...\n",
zRepo, zWorkDir);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " open ", -1);
blob_append_escaped_arg(&cmd, zRepo, 1);
| | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
Blob cmd;
fossil_print("opening the new %s repository in directory %s...\n",
zRepo, zWorkDir);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " open ", -1);
blob_append_escaped_arg(&cmd, zRepo, 1);
blob_append(&cmd, " --nosync --workdir ", -1);
blob_append_escaped_arg(&cmd, zWorkDir, 1);
if( allowNested ){
blob_append(&cmd, " --nested", -1);
}
fossil_system(blob_str(&cmd));
blob_reset(&cmd);
}
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
1912 1913 1914 1915 1916 1917 1918 |
if( file_size(zDbName, ExtFILE)<1024*3 ){
char *zHome = file_dirname(zDbName);
int rc;
if( file_isdir(zHome, ExtFILE)==0 ){
file_mkdir(zHome, ExtFILE, 0);
}
rc = file_access(zHome, W_OK);
| < > | 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 |
if( file_size(zDbName, ExtFILE)<1024*3 ){
char *zHome = file_dirname(zDbName);
int rc;
if( file_isdir(zHome, ExtFILE)==0 ){
file_mkdir(zHome, ExtFILE, 0);
}
rc = file_access(zHome, W_OK);
if( rc ){
if( isOptional ) return 0;
fossil_fatal("home directory \"%s\" must be writeable", zHome);
}
db_init_database(zDbName, zConfigSchema, (char*)0);
fossil_free(zHome);
}
if( file_access(zDbName, W_OK) ){
if( isOptional ) return 0;
fossil_fatal("configuration file %s must be writeable", zDbName);
}
if( useAttach ){
db_open_or_attach(zDbName, "configdb");
|
| ︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 |
/*
** Returns non-zero if support for symlinks is currently enabled.
*/
int db_allow_symlinks(void){
return g.allowSymlinks;
}
/*
** Open the repository database given by zDbName. If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
if( g.repositoryOpen ) return;
if( zDbName==0 ){
if( g.localOpen ){
zDbName = db_repository_filename();
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 |
/*
** Returns non-zero if support for symlinks is currently enabled.
*/
int db_allow_symlinks(void){
return g.allowSymlinks;
}
/*
** Return TRUE if the file in the argument seems like it might be an
** SQLite database file that contains a Fossil repository schema.
*/
int db_looks_like_a_repository(const char *zDbName){
sqlite3 *db = 0;
i64 sz;
int rc;
int res = 0;
sqlite3_stmt *pStmt = 0;
sz = file_size(zDbName, ExtFILE);
if( sz<16834 ) return 0;
if( sz & 0x1ff ) return 0;
rc = sqlite3_open(zDbName, &db);
if( rc ) goto is_repo_end;
rc = sqlite3_prepare_v2(db,
"SELECT count(*) FROM sqlite_schema"
" WHERE name COLLATE nocase IN"
"('blob','delta','rcvfrom','user','config','mlink','plink');",
-1, &pStmt, 0);
if( rc ) goto is_repo_end;
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) goto is_repo_end;
if( sqlite3_column_int(pStmt, 0)!=7 ) goto is_repo_end;
res = 1;
is_repo_end:
sqlite3_finalize(pStmt);
sqlite3_close(db);
return res;
}
/*
** COMMAND: test-is-repo
*/
void test_is_repo(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s: %s\n",
db_looks_like_a_repository(g.argv[i]) ? "yes" : " no",
g.argv[i]
);
}
}
/*
** Open the repository database given by zDbName. If zDbName==NULL then
** get the name from the already open local database.
*/
void db_open_repository(const char *zDbName){
i64 sz;
if( g.repositoryOpen ) return;
if( zDbName==0 ){
if( g.localOpen ){
zDbName = db_repository_filename();
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
if( file_access(zDbName, R_OK)
|| (sz = file_size(zDbName, ExtFILE))<16384
|| (sz&0x1ff)!=0
){
if( file_access(zDbName, F_OK) ){
#ifdef FOSSIL_ENABLE_JSON
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
#endif
fossil_fatal("repository does not exist or"
" is in an unreadable directory: %s", zDbName);
}else if( file_access(zDbName, R_OK) ){
|
| ︙ | ︙ | |||
3499 3500 3501 3502 3503 3504 3505 | ** Options: ** --empty Initialize checkout as being empty, but still connected ** with the local repository. If you commit this checkout, ** it will become a new "initial" commit in the repository. ** -f|--force Continue with the open even if the working directory is ** not empty. ** --force-missing Force opening a repository with missing content | | > > > | > | 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 |
** Options:
** --empty Initialize checkout as being empty, but still connected
** with the local repository. If you commit this checkout,
** it will become a new "initial" commit in the repository.
** -f|--force Continue with the open even if the working directory is
** not empty.
** --force-missing Force opening a repository with missing content
** -k|--keep Only modify the manifest and manifest.uuid files
** --nested Allow opening a repository inside an opened checkout
** --nosync Do not auto-sync the repository prior to opening
** --repodir DIR If REPOSITORY is a URI that will be cloned, store
** the clone in DIR rather than in "."
** --setmtime Set timestamps of all files to match their SCM-side
** times (the timestamp of the last checkin which modified
** them).
** --verbose If passed a URI then this flag is passed on to the clone
** operation, otherwise it has no effect.
** --workdir DIR Use DIR as the working directory instead of ".". The DIR
** directory is created if it does not exist.
**
** See also: [[close]], [[clone]]
*/
void cmd_open(void){
int emptyFlag;
int keepFlag;
int forceMissingFlag;
int allowNested;
int setmtimeFlag; /* --setmtime. Set mtimes on files */
int bForce = 0; /* --force. Open even if non-empty dir */
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
const char *zWorkDir; /* --workdir value */
const char *zRepo = 0; /* Name of the repository file */
const char *zRepoDir = 0; /* --repodir value */
char *zPwd; /* Initial working directory */
int isUri = 0; /* True if REPOSITORY is a URI */
int nLocal; /* Number of preexisting files in cwd */
int bNosync = 0; /* --nosync. Omit auto-sync */
int bVerbose = 0; /* --verbose option for clone */
url_proxy_options();
emptyFlag = find_option("empty",0,0)!=0;
keepFlag = find_option("keep","k",0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
allowNested = find_option("nested",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
zWorkDir = find_option("workdir",0,1);
zRepoDir = find_option("repodir",0,1);
bForce = find_option("force","f",0)!=0;
bNosync = find_option("nosync",0,0)!=0;
bVerbose = find_option("verbose",0,0)!=0;
zPwd = file_getcwd(0,0);
/* We should be done with options.. */
verify_all_options();
if( g.argc!=3 && g.argc!=4 ){
|
| ︙ | ︙ | |||
3580 3581 3582 3583 3584 3585 3586 |
}
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
| > > | | 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 |
}
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
"use the -f (--force) option to override\n"
"or the -k (--keep) option to keep local files unchanged",
file_getcwd(0,0));
}
if( db_open_local_v2(0, allowNested) ){
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
}
/* If REPOSITORY looks like a URI, then try to clone it first */
|
| ︙ | ︙ | |||
3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 |
}
if( zRepoDir==0 ) zRepoDir = zPwd;
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
fossil_free(zNewBase);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " clone", -1);
blob_append_escaped_arg(&cmd, zUri, 1);
blob_append_escaped_arg(&cmd, zRepo, 1);
zCmd = blob_str(&cmd);
fossil_print("%s\n", zCmd);
if( zWorkDir ) file_chdir(zPwd, 0);
rc = fossil_system(zCmd);
if( rc ){
| > > > | 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 |
}
if( zRepoDir==0 ) zRepoDir = zPwd;
zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase);
fossil_free(zNewBase);
blob_init(&cmd, 0, 0);
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_append(&cmd, " clone", -1);
if(0!=bVerbose){
blob_append(&cmd, " --verbose", -1);
}
blob_append_escaped_arg(&cmd, zUri, 1);
blob_append_escaped_arg(&cmd, zRepo, 1);
zCmd = blob_str(&cmd);
fossil_print("%s\n", zCmd);
if( zWorkDir ) file_chdir(zPwd, 0);
rc = fossil_system(zCmd);
if( rc ){
|
| ︙ | ︙ | |||
3805 3806 3807 3808 3809 3810 3811 | /* ** SETTING: auto-shun boolean default=on ** If enabled, automatically pull the shunning list ** from a server to which the client autosyncs. */ /* ** SETTING: autosync width=16 default=on | > | > | | | > > > | 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 | /* ** SETTING: auto-shun boolean default=on ** If enabled, automatically pull the shunning list ** from a server to which the client autosyncs. */ /* ** SETTING: autosync width=16 default=on ** This setting can be a boolean value (0, 1, on, off, true, false) ** or "pullonly" or "all". ** ** If not false, automatically pull prior to commit ** or update and automatically push after commit or ** tag or branch creation. Except, if the value is ** "pullonly" then only pull operations occur automatically. ** Normally, only the default remote is used, but if the ** value is "all" then push/pull operations occur on all ** remotes. */ /* ** SETTING: autosync-tries width=16 default=1 ** If autosync is enabled setting this to a value greater ** than zero will cause autosync to try no more than this ** number of attempts if there is a sync failure. */ |
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
file_delete(blob_str(&temp2));
blob_reset(&temp1);
blob_reset(&temp2);
blob_reset(&cmd);
}
}
/*
** Run a diff between the version zFrom and files on disk. zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
**
** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
| > > > > > > > > > > > > > > > > > > > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
file_delete(blob_str(&temp2));
blob_reset(&temp1);
blob_reset(&temp2);
blob_reset(&cmd);
}
}
/*
** Return true if the disk file is identical to the Blob. Return zero
** if the files differ in any way.
*/
static int file_same_as_blob(Blob *blob, const char *zDiskFile){
Blob file;
int rc = 0;
if( blob_size(blob)!=file_size(zDiskFile, ExtFILE) ) return 0;
blob_zero(&file);
blob_read_from_file(&file, zDiskFile, ExtFILE);
if( blob_size(&file)!=blob_size(blob) ){
rc = 0;
}else{
rc = memcmp(blob_buffer(&file), blob_buffer(blob), blob_size(&file))==0;
}
blob_reset(&file);
return rc;
}
/*
** Run a diff between the version zFrom and files on disk. zFrom might
** be NULL which means to simply show the difference between the edited
** files on disk and the check-out on which they are based.
**
** Use the internal diff logic if zDiffCmd is NULL. Otherwise call the
|
| ︙ | ︙ | |||
670 671 672 673 674 675 676 |
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
| > | | > | 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 |
continue;
}
if( srcid>0 ){
content_get(srcid, &content);
}else{
blob_zero(&content);
}
if( isChnged==0 || !file_same_as_blob(&content, zFullName) ){
diff_print_index(zPathname, pCfg, pOut);
diff_file(&content, zFullName, zPathname, pCfg, pOut);
}
blob_reset(&content);
}
blob_reset(&fname);
}
db_finalize(&q);
db_end_transaction(1); /* ROLLBACK */
}
|
| ︙ | ︙ |
Changes to src/fossil.bootstrap.js.
| ︙ | ︙ | |||
289 290 291 292 293 294 295 296 |
F.page.setPageTitle = function f(title){
const t = document.querySelector('title');
if(t) t.innerText = title || f.$orig;
return this;
};
F.onPageLoad(()=>F.page.setPageTitle.$orig
= document.querySelector('title').innerText);
})(window);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
F.page.setPageTitle = function f(title){
const t = document.querySelector('title');
if(t) t.innerText = title || f.$orig;
return this;
};
F.onPageLoad(()=>F.page.setPageTitle.$orig
= document.querySelector('title').innerText);
/**
Returns a function, that, as long as it continues to be invoked,
will not be triggered. The function will be called after it stops
being called for N milliseconds. If `immediate` is passed, call
the callback immediately and hinder future invocations until at
least the given time has passed.
If passed only 1 argument, or passed a falsy 2nd argument,
the default wait time set in this function's $defaultDelay
property is used.
Source: underscore.js, by way of https://davidwalsh.name/javascript-debounce-function
*/
F.debounce = function f(func, wait, immediate) {
var timeout;
if(!wait) wait = f.$defaultDelay;
return function() {
const context = this, args = Array.prototype.slice.call(arguments);
const later = function() {
timeout = undefined;
if(!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) func.apply(context, args);
};
};
F.debounce.$defaultDelay = 500 /*arbitrary*/;
})(window);
|
Changes to src/fossil.diff.js.
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
of the diff, only between two diff chunks.
*/
maybeReplaceButtons: function(){
if(this.pos.next && this.pos.prev
&& (this.pos.endLhs - this.pos.startLhs <= Diff.config.chunkLoadLines)){
D.clearElement(this.e.btnWrapper);
D.append(this.e.btnWrapper, this.createButton(this.FetchType.FillGap));
| | > | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
of the diff, only between two diff chunks.
*/
maybeReplaceButtons: function(){
if(this.pos.next && this.pos.prev
&& (this.pos.endLhs - this.pos.startLhs <= Diff.config.chunkLoadLines)){
D.clearElement(this.e.btnWrapper);
D.append(this.e.btnWrapper, this.createButton(this.FetchType.FillGap));
if( this.$fetchQueue && this.$fetchQueue.length>1 ){
this.$fetchQueue[1] = this.FetchType.FillGap;
this.$fetchQueue.length = 2;
}
}
return this;
},
/**
Callack for /jchunk responses.
|
| ︙ | ︙ | |||
575 576 577 578 579 580 581 |
if( this.pos.prev && this.pos.prev.endLhs >= up.from ){
up.from = this.pos.prev.endLhs + 1;
fetchType = this.FetchType.FillGap;
}
}
//console.debug("fetchChunk(",fetchType,")",up);
fOpt.onerror = function(err){
| > | | > > > | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
if( this.pos.prev && this.pos.prev.endLhs >= up.from ){
up.from = this.pos.prev.endLhs + 1;
fetchType = this.FetchType.FillGap;
}
}
//console.debug("fetchChunk(",fetchType,")",up);
fOpt.onerror = function(err){
if(self.e/*guard against a late-stage onerror() call*/){
self.msg(true,err.message);
self.$fetchQueue.length = 0;
}else{
Diff.config.chunkFetch.onerror.call(this,err);
}
};
Diff.fetchArtifactChunk(fOpt);
return this;
}
};
/**
|
| ︙ | ︙ | |||
730 731 732 733 734 735 736 |
return this;
}
window.fossil.page.tweakSbsDiffs = function(){
document.querySelectorAll('table.splitdiff').forEach((e)=>Diff.initTableDiff(e));
Diff.checkTableWidth();
};
Diff.initTableDiff().checkTableWidth();
| | | 735 736 737 738 739 740 741 742 743 |
return this;
}
window.fossil.page.tweakSbsDiffs = function(){
document.querySelectorAll('table.splitdiff').forEach((e)=>Diff.initTableDiff(e));
Diff.checkTableWidth();
};
Diff.initTableDiff().checkTableWidth();
window.addEventListener('resize', F.debounce(()=>Diff.checkTableWidth()));
}, false);
|
Changes to src/fossil.fetch.js.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | - onload: callback(responseData) (default = output response to the console). In the context of the callback, the options object is "this", noting that this call may have amended the options object with state other than what the caller provided. - onerror: callback(Error object) (default = output error message to console.error() and fossil.error()). Triggered if the request | | | > | > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | - onload: callback(responseData) (default = output response to the console). In the context of the callback, the options object is "this", noting that this call may have amended the options object with state other than what the caller provided. - onerror: callback(Error object) (default = output error message to console.error() and fossil.error()). Triggered if the request generates any response other than HTTP 200, suffers a connection error or timeout while awaiting a response, or if the onload() handler throws an exception. In the context of the callback, the options object is "this". Note that this function is intended to be used solely for error reporting, not error recovery. Because onerror() may be called if onload() throws, it is up to the caller to ensure that their onerror() callback references only state which is valid in such a case. - method: 'POST' | 'GET' (default = 'GET'). CASE SENSITIVE! - payload: anything acceptable by XHR2.send(ARG) (DOMString, Document, FormData, Blob, File, ArrayBuffer), or a plain object or array, either of which gets JSON.stringify()'d. If payload is set then the method is automatically set to 'POST'. By default XHR2 |
| ︙ | ︙ |
Changes to src/fossil.page.chat.js.
| ︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
Returns an almost-ISO8601 form of Date object d.
*/
const iso8601ish = function(d){
return d.toISOString()
.replace('T',' ').replace(/\.\d+/,'')
.replace('Z', ' zulu');
};
/** Returns the local time string of Date object d, defaulting
to the current time. */
const localTimeString = function ff(d){
d || (d = new Date());
return [
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
| > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
Returns an almost-ISO8601 form of Date object d.
*/
const iso8601ish = function(d){
return d.toISOString()
.replace('T',' ').replace(/\.\d+/,'')
.replace('Z', ' zulu');
};
const pad2 = (x)=>('0'+x).substr(-2);
/** Returns the local time string of Date object d, defaulting
to the current time. */
const localTimeString = function ff(d){
d || (d = new Date());
return [
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
|
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
var extra = 0;
if(com){
ht = wh;
}else{
elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false);
ht = wh - extra;
}
| | | | | < < < < | | > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
var extra = 0;
if(com){
ht = wh;
}else{
elemsToCount.forEach((e)=>e ? extra += D.effectiveHeight(e) : false);
ht = wh - extra;
}
f.chat.e.inputX.style.maxHeight = (ht/2)+"px";
/* ^^^^ this is a middle ground between having no size cap
on the input field and having a fixed arbitrary cap. */;
contentArea.style.height =
contentArea.style.maxHeight = [
"calc(", (ht>=100 ? ht : 100), "px",
" - 0.75em"/*fudge value*/,")"
/* ^^^^ hypothetically not needed, but both Chrome/FF on
Linux will force scrollbars on the body if this value is
too small (<0.75em in my tests). */
].join('');
if(false){
console.debug("resized.",wh, extra, ht,
window.getComputedStyle(contentArea).maxHeight,
contentArea);
console.debug("Set input max height to: ",
f.chat.e.inputX.style.maxHeight);
}
};
resized.$disabled = true/*gets deleted when setup is finished*/;
window.addEventListener('resize', F.debounce(resized, 250), false);
return resized;
})();
fossil.FRK = ForceResizeKludge/*for debugging*/;
const Chat = ForceResizeKludge.chat = (function(){
const cs = {
verboseErrors: false /* if true then certain, mostly extraneous,
error messages may be sent to the console. */,
e:{/*map of certain DOM elements.*/
messageInjectPoint: E1('#message-inject-point'),
pageTitle: E1('head title'),
loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */,
inputWrapper: E1("#chat-input-area"),
inputElementWrapper: E1('#chat-input-line-wrapper'),
fileSelectWrapper: E1('#chat-input-file-area'),
viewMessages: E1('#chat-messages-wrapper'),
btnSubmit: E1('#chat-button-submit'),
btnAttach: E1('#chat-button-attach'),
inputX: E1('#chat-input-field-x'),
input1: E1('#chat-input-field-single'),
inputM: E1('#chat-input-field-multi'),
inputFile: E1('#chat-input-file'),
contentDiv: E1('div.content'),
viewConfig: E1('#chat-config'),
viewPreview: E1('#chat-preview'),
previewContent: E1('#chat-preview-content'),
btnPreview: E1('#chat-button-preview'),
views: document.querySelectorAll('.chat-view'),
|
| ︙ | ︙ | |||
190 191 192 193 194 195 196 |
},
/** Gets (no args) or sets (1 arg) the current input text field value,
taking into account single- vs multi-line input. The getter returns
a string and the setter returns this object. */
inputValue: function(){
const e = this.inputElement();
if(arguments.length){
| > | | | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
},
/** Gets (no args) or sets (1 arg) the current input text field value,
taking into account single- vs multi-line input. The getter returns
a string and the setter returns this object. */
inputValue: function(){
const e = this.inputElement();
if(arguments.length){
if(e.isContentEditable) e.innerText = arguments[0];
else e.value = arguments[0];
return this;
}
return e.isContentEditable ? e.innerText : e.value;
},
/** Asks the current user input field to take focus. Returns this. */
inputFocus: function(){
this.inputElement().focus();
return this;
},
/** Returns the current message input element. */
inputElement: function(){
return this.e.inputFields[this.e.inputFields.$currentIndex];
},
/** Enables (if yes is truthy) or disables all elements in
* this.disableDuringAjax. */
enableAjaxComponents: function(yes){
D[yes ? 'enable' : 'disable'](this.disableDuringAjax);
return this;
},
|
| ︙ | ︙ | |||
413 414 415 416 417 418 419 |
/* When on, the edit field starts as a single line and
expands as the user types, and the relevant buttons are
laid out in a compact form. When off, the edit field and
buttons are larger. */
"edit-compact-mode": true,
/* When on, sets the font-family on messages and the edit
field to monospace. */
| | | > > > > > > | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
/* When on, the edit field starts as a single line and
expands as the user types, and the relevant buttons are
laid out in a compact form. When off, the edit field and
buttons are larger. */
"edit-compact-mode": true,
/* When on, sets the font-family on messages and the edit
field to monospace. */
"monospace-messages": false,
/* When on, non-chat UI elements (page header/footer) are
hidden */
"chat-only-mode": false,
/* When set to a URI, it is assumed to be an audio file,
which gets played when new messages arrive. When true,
the first entry in the audio file selection list will be
used. */
"audible-alert": true,
/* When on, show the list of "active" users - those from
whom we have messages in the currently-loaded history
(noting that deletions are also messages). */
"active-user-list": false,
/* When on, the [active-user-list] setting includes the
timestamp of each user's most recent message. */
"active-user-list-timestamps": false,
/* When on, the [audible-alert] is played for one's own
messages, else it is only played for other users'
messages. */
"alert-own-messages": false,
/* "Experimental mode" input: use a contenteditable field
for input. This is generally more comfortable to use,
and more modern, than plain text input fields, but
the list of browser-specific quirks and bugs is...
not short. */
"edit-widget-x": false
}
},
/** Plays a new-message notification sound IF the audible-alert
setting is true, else this is a no-op. Returns this.
*/
playNewMessageSound: function f(){
if(f.uri){
|
| ︙ | ︙ | |||
670 671 672 673 674 675 676 |
animate: function f(e,a,cb){
if(!f.$disabled){
D.addClassBriefly(e, a, 0, cb);
}
return this;
}
};
| > > > > > > | | | 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
animate: function f(e,a,cb){
if(!f.$disabled){
D.addClassBriefly(e, a, 0, cb);
}
return this;
}
};
cs.e.inputFields = [ cs.e.input1, cs.e.inputM, cs.e.inputX ];
cs.e.inputFields.$currentIndex = 0;
cs.e.inputFields.forEach(function(e,ndx){
if(ndx===cs.e.inputFields.$currentIndex) D.removeClass(e,'hidden');
else D.addClass(e,'hidden');
});
if(D.attr(cs.e.inputX,'contenteditable','plaintext-only').isContentEditable){
cs.$browserHasPlaintextOnly = true;
}else{
/* Only the Chrome family supports contenteditable=plaintext-only */
cs.$browserHasPlaintextOnly = false;
D.attr(cs.e.inputX,'contenteditable','true');
}
cs.animate.$disabled = true;
F.fetch.beforesend = ()=>cs.ajaxStart();
F.fetch.aftersend = ()=>cs.ajaxEnd();
cs.pageTitleOrig = cs.e.pageTitle.innerText;
const qs = (e)=>document.querySelector(e);
const argsToArray = function(args){
|
| ︙ | ︙ | |||
700 701 702 703 704 705 706 |
};
/**
Reports an error in the form of a new message in the chat
feed. All arguments are appended to the message's content area
using fossil.dom.append(), so may be of any type supported by
that function.
*/
| | > | > > | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 |
};
/**
Reports an error in the form of a new message in the chat
feed. All arguments are appended to the message's content area
using fossil.dom.append(), so may be of any type supported by
that function.
*/
cs.reportErrorAsMessage = function f(/*msg args*/){
if(undefined === f.$msgid) f.$msgid=0;
const args = argsToArray(arguments).map(function(v){
return (v instanceof Error) ? v.message : v;
});
console.error("chat error:",args);
const d = new Date().toISOString(),
mw = new this.MessageWidget({
isError: true,
xfrom: null,
msgid: "error-"+(++f.$msgid),
mtime: d,
lmtime: d,
xmsg: args
});
this.injectMessageElem(mw.e.body);
mw.scrollIntoView();
};
|
| ︙ | ︙ | |||
871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
this.deleteMessageElem(id);
}
};
document.addEventListener('visibilitychange', function(ev){
cs.pageIsActive = ('visible' === document.visibilityState);
if(cs.pageIsActive){
cs.e.pageTitle.innerText = cs.pageTitleOrig;
}
}, true);
cs.setCurrentView(cs.e.viewMessages);
cs.e.activeUserList.addEventListener('click', function f(ev){
/* Filter messages on a user clicked in activeUserList */
ev.stopPropagation();
| > > > > > > > > > > | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 |
this.deleteMessageElem(id);
}
};
document.addEventListener('visibilitychange', function(ev){
cs.pageIsActive = ('visible' === document.visibilityState);
if(cs.pageIsActive){
cs.e.pageTitle.innerText = cs.pageTitleOrig;
if(document.activeElement!==cs.inputElement()){
/* An attempt to resolve usability problem reported by Joe
M. where the Pale Moon browser is giving input focus to
the Preview button. The down-side of this is that it will
deselect any text which was previously selected on this
page. This also, unfortunately, places the focus at the
start of the element, rather than the last cursor position
(like a textarea would). */
setTimeout(()=>cs.inputFocus(), 0);
}
}
}, true);
cs.setCurrentView(cs.e.viewMessages);
cs.e.activeUserList.addEventListener('click', function f(ev){
/* Filter messages on a user clicked in activeUserList */
ev.stopPropagation();
|
| ︙ | ︙ | |||
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
e.dataset.hashtag = e.dataset.hashtag.toLowerCase();
e.addEventListener('click', f.$click, false);
})
elem.querySelectorAll('[data-numtag]').forEach(
(e)=>e.addEventListener('click', f.$clickNum, false)
)
}/*setupHashtags()*/;
/**
Custom widget type for rendering messages (one message per
instance). These are modelled after FIELDSET elements but we
don't use FIELDSET because of cross-browser inconsistencies in
features of the FIELDSET/LEGEND combination, e.g. inability to
align legends via CSS in Firefox and clicking-related
| > > > > > > > > > | 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 |
e.dataset.hashtag = e.dataset.hashtag.toLowerCase();
e.addEventListener('click', f.$click, false);
})
elem.querySelectorAll('[data-numtag]').forEach(
(e)=>e.addEventListener('click', f.$clickNum, false)
)
}/*setupHashtags()*/;
/** Returns the first .message-widget element in DOM element
e's lineage. */
const findMessageWidgetParent = function(e){
while( e && !e.classList.contains('message-widget')){
e = e.parentNode;
}
return e;
};
/**
Custom widget type for rendering messages (one message per
instance). These are modelled after FIELDSET elements but we
don't use FIELDSET because of cross-browser inconsistencies in
features of the FIELDSET/LEGEND combination, e.g. inability to
align legends via CSS in Firefox and clicking-related
|
| ︙ | ︙ | |||
1014 1015 1016 1017 1018 1019 1020 |
D.append(this.e.body, this.e.tab, this.e.content);
this.e.tab.setAttribute('role', 'button');
if(arguments.length){
this.setMessage(arguments[0]);
}
};
/* Left-zero-pad a number to at least 2 digits */
| < > | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 |
D.append(this.e.body, this.e.tab, this.e.content);
this.e.tab.setAttribute('role', 'button');
if(arguments.length){
this.setMessage(arguments[0]);
}
};
/* Left-zero-pad a number to at least 2 digits */
const dowMap = {
/* Map of Date.getDay() values to weekday names. */
0: "Sunday", 1: "Monday", 2: "Tuesday",
3: "Wednesday", 4: "Thursday", 5: "Friday",
6: "Saturday"
};
/* Given a Date, returns the timestamp string used in the
"tab" part of message widgets. */
const theTime = function(d){
return [
//d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
//'-',pad2(d.getDate()), ' ',
d.getHours(),":",
(d.getMinutes()+100).toString().slice(1,3),
' ', dowMap[d.getDay()]
].join('');
};
cf.prototype = {
scrollIntoView: function(){
this.e.content.scrollIntoView();
},
setMessage: function(m){
const ds = this.e.body.dataset;
ds.timestamp = m.mtime;
|
| ︙ | ︙ | |||
1066 1067 1068 1069 1070 1071 1072 |
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
this.e.tab,
| | | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
this.e.tab,
D.append(D.code(), 'notification @ ',theTime(d))
);
}
if( m.xfrom && m.fsize>0 ){
if( m.fmime
&& m.fmime.startsWith("image/")
&& Chat.settings.getBool('images-inline',true)
){
|
| ︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 |
// sense that it is not possible for a malefactor to inject HTML
// or javascript or CSS. The m.xmsg content might contain
// hyperlinks, but otherwise it will be markup-free. See the
// chat_format_to_html() routine in the server for details.
//
// Hence, even though innerHTML is normally frowned upon, it is
// perfectly safe to use in this context.
| | > > | 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 |
// sense that it is not possible for a malefactor to inject HTML
// or javascript or CSS. The m.xmsg content might contain
// hyperlinks, but otherwise it will be markup-free. See the
// chat_format_to_html() routine in the server for details.
//
// Hence, even though innerHTML is normally frowned upon, it is
// perfectly safe to use in this context.
if(m.xmsg && 'string' !== typeof m.xmsg){
// Used by Chat.reportErrorAsMessage()
D.append(contentTarget, m.xmsg);
}else{
contentTarget.innerHTML = m.xmsg;
contentTarget.querySelectorAll('a').forEach(addAnchorTargetBlank);
setupHashtags(contentTarget);
if(F.pikchr){
F.pikchr.addSrcView(contentTarget.querySelectorAll('svg.pikchr'));
}
}
}
//console.debug("tab",this.e.tab);
//console.debug("this.e.tab.firstElementChild",this.e.tab.firstElementChild);
this.e.tab.firstElementChild.addEventListener('click', this._handleLegendClicked, false);
/*if(eXFrom){
eXFrom.addEventListener('click', ()=>this.e.tab.click(), false);
}*/
return this;
},
/* Event handler for clicking .message-user elements to show their
|
| ︙ | ︙ | |||
1247 1248 1249 1250 1251 1252 1253 |
return;
}
this.$eMsg = tgtMsg;
this.refresh();
}
}/*f.popup*/;
}/*end static init*/
| | < < < | 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 |
return;
}
this.$eMsg = tgtMsg;
this.refresh();
}
}/*f.popup*/;
}/*end static init*/
const theMsg = findMessageWidgetParent(ev.target);
if(theMsg) f.popup.show(theMsg);
}/*_handleLegendClicked()*/
}/*MessageWidget.prototype*/;
/** Assumes that e is a MessageWidget element, ensures that
Chat.e.viewMessages is visible, scrolls the message,
and animates it a bit to make it more visible. */
cf.scrollToMessageElem = function(e){
|
| ︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 |
D.clearElement(this.dropDetails);
Chat.e.inputFile.value = "";
}
};
/** Updates the paste/drop zone with details of the pasted/dropped
data. The argument must be a Blob or Blob-like object (File) or
it can be falsy to reset/clear that state.*/
| | | 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 |
D.clearElement(this.dropDetails);
Chat.e.inputFile.value = "";
}
};
/** Updates the paste/drop zone with details of the pasted/dropped
data. The argument must be a Blob or Blob-like object (File) or
it can be falsy to reset/clear that state.*/
const updateDropZoneContent = bxs.updateDropZoneContent = function(blob){
//console.debug("updateDropZoneContent()",blob);
const dd = bxs.dropDetails;
bxs.blob = blob;
D.clearElement(dd);
if(!blob){
Chat.e.inputFile.value = '';
return;
|
| ︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 |
document.addEventListener('paste', pasteListener, true);
if(window.Selection && window.Range && !Chat.$browserHasPlaintextOnly){
/* Acrobatics to keep *some* installations of Firefox
from pasting formatting into contenteditable fields.
This also works on Chrome, but chrome has the
contenteditable=plaintext-only property which does this
for us. */
| | | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 |
document.addEventListener('paste', pasteListener, true);
if(window.Selection && window.Range && !Chat.$browserHasPlaintextOnly){
/* Acrobatics to keep *some* installations of Firefox
from pasting formatting into contenteditable fields.
This also works on Chrome, but chrome has the
contenteditable=plaintext-only property which does this
for us. */
Chat.e.inputX.addEventListener(
'paste',
function(ev){
if (ev.clipboardData && ev.clipboardData.getData) {
const pastedText = ev.clipboardData.getData('text/plain');
const selection = window.getSelection();
if (!selection.rangeCount) return false;
selection.deleteFromDocument(/*remove selected content*/);
|
| ︙ | ︙ | |||
1354 1355 1356 1357 1358 1359 1360 |
which is not compatible with how we use it, so... */
ev.dataTransfer.effectAllowed = 'none';
ev.dataTransfer.dropEffect = 'none';
ev.preventDefault();
ev.stopPropagation();
return false;
};
| < < | < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 |
which is not compatible with how we use it, so... */
ev.dataTransfer.effectAllowed = 'none';
ev.dataTransfer.dropEffect = 'none';
ev.preventDefault();
ev.stopPropagation();
return false;
};
['drop','dragenter','dragleave','dragend'].forEach(
(k)=>Chat.e.inputX.addEventListener(k, noDragDropEvents, false)
);
return bxs;
})()/*drag/drop/paste*/;
const tzOffsetToString = function(off){
const hours = Math.round(off/60), min = Math.round(off % 30);
return ''+(hours + (min ? '.5' : ''));
};
const localTime8601 = function(d){
return [
d.getYear()+1900, '-', pad2(d.getMonth()+1), '-', pad2(d.getDate()),
'T', pad2(d.getHours()),':', pad2(d.getMinutes()),':',pad2(d.getSeconds())
].join('');
};
/**
Called by Chat.submitMessage() when message sending failed. Injects a fake message
containing the content and attachment of the failed message and gives the user buttons
to discard it or edit and retry.
*/
const recoverFailedMessage = function(state){
const w = D.addClass(D.div(), 'failed-message');
D.append(w, D.append(
D.span(),"This message was not successfully sent to the server:"
));
if(state.msg){
const ta = D.textarea();
ta.value = state.msg;
D.append(w,ta);
}
if(state.blob){
D.append(w,D.append(D.span(),"Attachment: ",(state.blob.name||"unnamed")));
//console.debug("blob = ",state.blob);
}
const buttons = D.addClass(D.div(), 'buttons');
D.append(w, buttons);
D.append(buttons, D.button("Discard message?", function(){
let theMsg = findMessageWidgetParent(w);
if(theMsg) Chat.deleteMessageElem(theMsg);
}));
D.append(buttons, D.button("Edit message and try again?", function(){
if(state.msg) Chat.inputValue(ta.value);
if(state.blob) BlobXferState.updateDropZoneContent(state.blob);
let theMsg = findMessageWidgetParent(w);
if(theMsg) Chat.deleteMessageElem(theMsg);
}));
Chat.reportErrorAsMessage(w);
};
/**
Submits the contents of the message input field (if not empty)
and/or the file attachment field to the server. If both are
empty, this is a no-op.
*/
Chat.submitMessage = function f(){
if(!f.spaces){
f.spaces = /\s+$/;
f.markdownContinuation = /\\\s+$/;
}
this.setCurrentView(this.e.viewMessages);
const fd = new FormData();
const fallback = {msg: this.inputValue()};
var msg = fallback.msg.trim();
if(msg && (msg.indexOf('\n')>0 || f.spaces.test(msg))){
/* Cosmetic: trim whitespace from the ends of lines to try to
keep copy/paste from terminals, especially wide ones, from
forcing a horizontal scrollbar on all clients. This breaks
markdown's use of blackslash-space-space for paragraph
continuation, but *not* doing this affects all clients every
time someone pastes in console copy/paste from an affected
|
| ︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 |
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
if( !msg && !file ) return;
const self = this;
fd.set("lmtime", localTime8601(new Date()));
F.fetch("chat-send",{
payload: fd,
responseType: 'text',
| > > | > > < > | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 |
});
msg = xmsg.join('\n');
}
if(msg) fd.set('msg',msg);
const file = BlobXferState.blob || this.e.inputFile.files[0];
if(file) fd.set("file", file);
if( !msg && !file ) return;
fallback.blob = file;
const self = this;
fd.set("lmtime", localTime8601(new Date()));
F.fetch("chat-send",{
payload: fd,
responseType: 'text',
onerror:function(err){
self.reportErrorAsMessage(err);
recoverFailedMessage(fallback);
},
onload:function(txt){
if(!txt) return/*success response*/;
try{
const json = JSON.parse(txt);
self.newContent({msgs:[json]});
}catch(e){
self.reportError(e);
}
recoverFailedMessage(fallback);
}
});
BlobXferState.clear();
Chat.inputValue("").inputFocus();
};
const inputWidgetKeydown = function f(ev){
|
| ︙ | ︙ | |||
1492 1493 1494 1495 1496 1497 1498 |
/* Ship it! */
ev.preventDefault();
ev.stopPropagation();
Chat.submitMessage();
return false;
}
};
| > | > | 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 |
/* Ship it! */
ev.preventDefault();
ev.stopPropagation();
Chat.submitMessage();
return false;
}
};
Chat.e.inputFields.forEach(
(e)=>e.addEventListener('keydown', inputWidgetKeydown, false)
);
Chat.e.btnSubmit.addEventListener('click',(e)=>{
e.preventDefault();
Chat.submitMessage();
return false;
});
Chat.e.btnAttach.addEventListener(
'click', ()=>Chat.e.inputFile.click(), false);
|
| ︙ | ︙ | |||
1551 1552 1553 1554 1555 1556 1557 |
}/*namedOptions.activeUsers additional setup*/
/**
Settings options structure: an array of Objects with the
following properties:
label: string for the UI
| | | | > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > | | | < | | | | | | | | | | | < | | > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | < < < < | | > | < < < < > | 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 |
}/*namedOptions.activeUsers additional setup*/
/**
Settings options structure: an array of Objects with the
following properties:
label: string for the UI
boolValue: string (name of Chat.settings setting) or a function
which returns true or false. If it is a string, it gets
replaced by a function which returns
Chat.settings.getBool(thatString) and the string gets assigned
to the persistentSetting property of this object.
select: SELECT element (instead of boolValue)
callback: optional handler to call after setting is modified.
It gets passed the setting object: {key:string, value:something}.
Its "this" is the options object. If this object has a
boolValue string or a persistentSetting property, the argument
passed to the callback is a settings object in the form {key:K,
value:V}. If this object does not have boolValue string or
persistentSetting then the callback is passed an event object
in response to the config option's UI widget being activated,
normally a 'change' event.
children: [array of settings objects]. These get listed under
this element and indented slightly for visual grouping. Only
one level of indention is supported.
Elements which only have a label and maybe a hint and
children can be used as headings.
If a setting has a boolValue set, that gets rendered as a
checkbox which toggles the given persistent setting (if
boolValue is a string) AND listens for changes to that setting
fired via Chat.settings.set() so that the checkbox can stay in
sync with external changes to that setting. Various Chat UI
elements stay in sync with the config UI via those settings
events. The checkbox element gets added to the options object
so that the callback() can reference it via this.checkbox.
*/
const settingsOps = [{
label: "Chat Configuration Options",
hint: F.storage.isTransient()
? "Local store is unavailable. These settings are transient."
: ["Most of these settings are persistent via ",
F.storage.storageImplName(), ": ",
F.storage.storageHelpDescription()].join('')
},{
label: "Editing Options...",
children:[{
label: "Chat-only mode",
hint: "Toggle the page between normal fossil view and chat-only view.",
boolValue: 'chat-only-mode'
},{
label: "Ctrl-enter to Send",
hint: [
"When on, only Ctrl-Enter will send messages and Enter adds ",
"blank lines. When off, both Enter and Ctrl-Enter send. ",
"When the input field has focus and is empty ",
"then Ctrl-Enter toggles this setting."
].join(''),
boolValue: 'edit-ctrl-send'
},{
label: "Compact mode",
hint: [
"Toggle between a space-saving or more spacious writing area. ",
"When the input field has focus, is empty, and preview mode ",
"is NOT active then Shift-Enter toggles this setting."].join(''),
boolValue: 'edit-compact-mode'
},{
label: "Use 'contenteditable' editing mode",
boolValue: 'edit-widget-x',
hint: [
"When enabled, chat input uses a so-called 'contenteditable' ",
"field. Though generally more comfortable and modern than ",
"plain-text input fields, browser-specific quirks and bugs ",
"may lead to frustration. Ideal for mobile devices."
].join('')
}]
},{
label: "Appearance Options...",
children:[{
label: "Left-align my posts",
hint: "Default alignment of your own messages is selected "
+ "based window width/height ratio.",
boolValue: ()=>!document.body.classList.contains('my-messages-right'),
callback: function f(){
document.body.classList[
this.checkbox.checked ? 'remove' : 'add'
]('my-messages-right');
}
},{
label: "Monospace message font",
hint: "Use monospace font for message and input text.",
boolValue: 'monospace-messages',
callback: function(setting){
document.body.classList[
setting.value ? 'add' : 'remove'
]('monospace-messages');
}
},{
label: "Show images inline",
hint: "When enabled, attached images are shown inline, "+
"else they appear as a download link.",
boolValue: 'images-inline'
}]
}];
/** Set up selection list of notification sounds. */
if(1){
const selectSound = D.select();
D.option(selectSound, "", "(no audio)");
const firstSoundIndex = selectSound.options.length;
|
| ︙ | ︙ | |||
1639 1640 1641 1642 1643 1644 1645 |
/* Missing file - removed after this setting was
applied. Fall back to the first sound in the list. */
selectSound.selectedIndex = firstSoundIndex;
}
}
Chat.setNewMessageSound(selectSound.value);
settingsOps.push({
| > | > > | | | | | | | | < < | | | | | > > > > > > > > > > > > > > > > | | > < | > > | | > > | > | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | | > > > | 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 |
/* Missing file - removed after this setting was
applied. Fall back to the first sound in the list. */
selectSound.selectedIndex = firstSoundIndex;
}
}
Chat.setNewMessageSound(selectSound.value);
settingsOps.push({
label: "Sound Options...",
hint: "How to enable audio playback is browser-specific!",
children:[{
hint: "Audio alert",
select: selectSound,
callback: function(ev){
const v = ev.target.value;
Chat.setNewMessageSound(v);
F.toast.message("Audio notifications "+(v ? "enabled" : "disabled")+".");
if(v) setTimeout(()=>Chat.playNewMessageSound(), 0);
}
},{
label: "Play notification for your own messages",
hint: "When enabled, the audio notification will be played for all messages, "+
"including your own. When disabled only messages from other users "+
"will trigger a notification.",
boolValue: 'alert-own-messages'
}]
});
}/*audio notification config*/
settingsOps.push({
label: "Active User List...",
hint: [
"/chat cannot track active connections, but it can tell ",
"you who has posted recently..."].join(''),
children:[
namedOptions.activeUsers,{
label: "Timestamps in active users list",
indent: true,
hint: "Show most recent message timestamps in the active user list.",
boolValue: 'active-user-list-timestamps'
}
]
});
/**
Build UI for config options...
*/
settingsOps.forEach(function f(op,indentOrIndex){
const menuEntry = D.addClass(D.div(), 'menu-entry');
if(true===indentOrIndex) D.addClass(menuEntry, 'child');
const label = op.label
? D.append(D.label(),op.label) : undefined;
const labelWrapper = D.addClass(D.div(), 'label-wrapper');
var hint;
if(op.hint){
hint = D.append(D.addClass(D.label(),'hint'),op.hint);
}
if(op.hasOwnProperty('select')){
const col0 = D.addClass(D.span(/*empty, but for spacing*/),
'toggle-wrapper');
D.append(menuEntry, labelWrapper, col0);
D.append(labelWrapper, op.select);
if(hint) D.append(labelWrapper, hint);
if(label) D.append(label);
if(op.callback){
op.select.addEventListener('change', (ev)=>op.callback(ev), false);
}
}else if(op.hasOwnProperty('boolValue')){
if(undefined === f.$id) f.$id = 0;
++f.$id;
if('string' ===typeof op.boolValue){
const key = op.boolValue;
op.boolValue = ()=>Chat.settings.getBool(key);
op.persistentSetting = key;
}
const check = op.checkbox
= D.attr(D.checkbox(1, op.boolValue()),
'aria-label', op.label);
const id = 'cfgopt'+f.$id;
const col0 = D.addClass(D.span(), 'toggle-wrapper');
check.checked = op.boolValue();
op.checkbox = check;
D.attr(check, 'id', id);
if(hint) D.attr(hint, 'for', id);
D.append(menuEntry, labelWrapper, col0);
D.append(col0, check);
if(label){
D.attr(label, 'for', id);
D.append(labelWrapper, label);
}
if(hint) D.append(labelWrapper, hint);
}else{
if(op.callback){
menuEntry.addEventListener('click', (ev)=>op.callback(ev));
}
D.append(menuEntry, labelWrapper);
if(label) D.append(labelWrapper, label);
if(hint) D.append(labelWrapper, hint);
}
D.append(optionsMenu, menuEntry);
if(op.persistentSetting){
Chat.settings.addListener(
op.persistentSetting,
function(setting){
if(op.checkbox) op.checkbox.checked = !!setting.value;
else if(op.select) op.select.value = setting.value;
if(op.callback) op.callback(setting);
}
);
if(op.checkbox){
op.checkbox.addEventListener(
'change', function(){
Chat.settings.set(op.persistentSetting, op.checkbox.checked)
}, false);
}
}else if(op.callback && op.checkbox){
op.checkbox.addEventListener('change', (ev)=>op.callback(ev), false);
}
if(op.children){
D.addClass(menuEntry, 'parent');
op.children.forEach((x)=>f(x,true));
}
});
})()/*#chat-button-settings setup*/;
(function(){
/* Install default settings... must come after
chat-button-settings setup so that the listeners which that
installs are notified via the properties getting initialized
here. */
Chat.settings.addListener('monospace-messages',function(s){
document.body.classList[s.value ? 'add' : 'remove']('monospace-messages');
})
Chat.settings.addListener('active-user-list',function(s){
Chat.showActiveUserList(s.value);
});
Chat.settings.addListener('active-user-list-timestamps',function(s){
Chat.showActiveUserTimestamps(s.value);
});
Chat.settings.addListener('chat-only-mode',function(s){
Chat.chatOnlyMode(s.value);
});
Chat.settings.addListener('edit-widget-x',function(s){
let eSelected;
if(s.value){
if(Chat.e.inputX===Chat.inputElement()) return;
eSelected = Chat.e.inputX;
}else{
eSelected = Chat.settings.getBool('edit-compact-mode')
? Chat.e.input1 : Chat.e.inputM;
}
const v = Chat.inputValue();
Chat.inputValue('');
Chat.e.inputFields.forEach(function(e,ndx){
if(eSelected===e){
Chat.e.inputFields.$currentIndex = ndx;
D.removeClass(e, 'hidden');
}
else D.addClass(e,'hidden');
});
Chat.inputValue(v);
eSelected.focus();
});
Chat.settings.addListener('edit-compact-mode',function(s){
if(Chat.e.inputX!==Chat.inputElement()){
/* Text field/textarea mode: swap them if needed.
Compact mode of inputX is toggled via CSS. */
const a = s.value
? [Chat.e.input1, Chat.e.inputM, 0]
: [Chat.e.inputM, Chat.e.input1, 1];
const v = Chat.inputValue();
Chat.inputValue('');
Chat.e.inputFields.$currentIndex = a[2];
Chat.inputValue(v);
D.removeClass(a[0], 'hidden');
D.addClass(a[1], 'hidden');
}
Chat.e.inputElementWrapper.classList[
s.value ? 'add' : 'remove'
]('compact');
Chat.e.inputFields[Chat.e.inputFields.$currentIndex].focus();
});
Chat.settings.addListener('edit-ctrl-send',function(s){
const label = (s.value ? "Ctrl-" : "")+"Enter submits messages.";
Chat.e.inputFields.forEach((e)=>{
const v = e.dataset.placeholder0 + " " +label;
if(e.isContentEditable) e.dataset.placeholder = v;
else D.attr(e,'placeholder',v);
});
Chat.e.btnSubmit.title = label;
});
const valueKludges = {
/* Convert certain string-format values to other types... */
"false": false,
"true": true
};
|
| ︙ | ︙ | |||
1782 1783 1784 1785 1786 1787 1788 |
this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
setupHashtags(this.e.previewContent)/*arguable, for usability reasons*/;
this.inputFocus();
};
Chat.e.viewPreview.querySelector('#chat-preview-close').
addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
let previewPending = false;
| | | 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 |
this.e.viewPreview.querySelectorAll('a').forEach(addAnchorTargetBlank);
setupHashtags(this.e.previewContent)/*arguable, for usability reasons*/;
this.inputFocus();
};
Chat.e.viewPreview.querySelector('#chat-preview-close').
addEventListener('click', ()=>Chat.setCurrentView(Chat.e.viewMessages), false);
let previewPending = false;
const elemsToEnable = [btnPreview, Chat.e.btnSubmit, Chat.e.inputFields];
const submit = function(ev){
ev.preventDefault();
ev.stopPropagation();
if(previewPending) return false;
const txt = Chat.inputValue();
if(!txt){
Chat.setPreviewText('');
|
| ︙ | ︙ |
Changes to src/http_socket.c.
| ︙ | ︙ | |||
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
struct addrinfo *ai = 0;
struct addrinfo hints;
char zRemote[NI_MAXHOST];
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
&& ai!=0
&& getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
}
if( ai ) freeaddrinfo(ai);
| > > > | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
struct addrinfo *ai = 0;
struct addrinfo hints;
char zRemote[NI_MAXHOST];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
fossil_free(g.zIpAddr);
g.zIpAddr = 0;
if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
&& ai!=0
&& getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
}
if( ai ) freeaddrinfo(ai);
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
fossil_warning("The remote server requested a client certificate for "
"authentication. Specify the pathname to a file containing the PEM "
"encoded certificate and private key with the --ssl-identity option "
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
void ssl_global_init(void){
const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
const char *identityFile;
if( sslIsInit==0 ){
SSL_library_init();
SSL_load_error_strings();
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){
fossil_warning("The remote server requested a client certificate for "
"authentication. Specify the pathname to a file containing the PEM "
"encoded certificate and private key with the --ssl-identity option "
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp.
**
** Per RFC 5280, ASN1 timestamps in X.509 certificates must
** be in UTC (Zulu timezone) with no fractional seconds.
**
** If showUtc==1, add " UTC" at the end of the returned string. This is
** not ISO8601-compliant, but makes the displayed value more user-friendly.
*/
static const char *ssl_asn1time_to_iso8601(ASN1_TIME *asn1_time,
int showUtc){
assert( showUtc==0 || showUtc==1 );
if( !ASN1_TIME_check(asn1_time) ){
return mprintf("Bad time value");
}else{
char res[20];
char *pr = res;
const char *pt = (char *)asn1_time->data;
/* 0123456789 1234
** UTCTime: YYMMDDHHMMSSZ (YY >= 50 ? 19YY : 20YY)
** GeneralizedTime: YYYYMMDDHHMMSSZ */
if( asn1_time->length < 15 ){
/* UTCTime, fill out century digits */
*pr++ = pt[0]>='5' ? '1' : '2';
*pr++ = pt[0]>='5' ? '9' : '0';
}else{
/* GeneralizedTime, copy century digits and advance source */
*pr++ = pt[0]; *pr++ = pt[1];
pt += 2;
}
*pr++ = pt[0]; *pr++ = pt[1]; *pr++ = '-';
*pr++ = pt[2]; *pr++ = pt[3]; *pr++ = '-';
*pr++ = pt[4]; *pr++ = pt[5]; *pr++ = ' ';
*pr++ = pt[6]; *pr++ = pt[7]; *pr++ = ':';
*pr++ = pt[8]; *pr++ = pt[9]; *pr++ = ':';
*pr++ = pt[10]; *pr++ = pt[11]; *pr = '\0';
return mprintf("%s%s", res, (showUtc ? " UTC" : ""));
}
}
/*
** Call this routine once before any other use of the SSL interface.
** This routine does initial configuration of the SSL module.
*/
void ssl_global_init(void){
const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
const char *identityFile;
if( sslIsInit==0 ){
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
sslCtx = SSL_CTX_new(SSLv23_client_method());
/* Disable SSLv2 and SSLv3 */
SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3);
/* Set up acceptable CA root certificates */
zCaSetting = db_get("ssl-ca-location", 0);
|
| ︙ | ︙ | |||
336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
if ( cert==NULL ){
ssl_set_errmsg("No SSL certificate was presented by the peer");
ssl_close();
return 1;
}
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
int x, desclen;
char *desc, *prompt;
Blob ans;
char cReply;
BIO *mem;
unsigned char md[EVP_MAX_MD_SIZE];
| > > > > > > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
if ( cert==NULL ){
ssl_set_errmsg("No SSL certificate was presented by the peer");
ssl_close();
return 1;
}
/* Debugging hint: On unix-like system, run something like:
**
** SSL_CERT_DIR=/tmp ./fossil sync
**
** to cause certificate validation to fail, and thus test the fallback
** logic.
*/
if( !sslNoCertVerify && SSL_get_verify_result(ssl)!=X509_V_OK ){
int x, desclen;
char *desc, *prompt;
Blob ans;
char cReply;
BIO *mem;
unsigned char md[EVP_MAX_MD_SIZE];
|
| ︙ | ︙ | |||
369 370 371 372 373 374 375 |
if( ssl_certificate_exception_exists(pUrlData, zHash) ){
/* Ignore the failure because an exception exists */
ssl_one_time_exception(pUrlData, zHash);
}else{
/* Tell the user about the failure and ask what to do */
mem = BIO_new(BIO_s_mem());
| | | > > > > | | < | > > > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
if( ssl_certificate_exception_exists(pUrlData, zHash) ){
/* Ignore the failure because an exception exists */
ssl_one_time_exception(pUrlData, zHash);
}else{
/* Tell the user about the failure and ask what to do */
mem = BIO_new(BIO_s_mem());
BIO_puts(mem, " subject: ");
X509_NAME_print_ex(mem, X509_get_subject_name(cert), 0, XN_FLAG_ONELINE);
BIO_puts(mem, "\n issuer: ");
X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
BIO_printf(mem, "\n notBefore: %s",
ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1));
BIO_printf(mem, "\n notAfter: %s",
ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1));
BIO_printf(mem, "\n sha256: %s", zHash);
desclen = BIO_get_mem_data(mem, &desc);
prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n"
"accept this cert and continue (y/N/fingerprint)? ",
pUrlData->name, desclen, desc);
BIO_free(mem);
prompt_user(prompt, &ans);
free(prompt);
cReply = blob_str(&ans)[0];
if( cReply!='y' && cReply!='Y'
&& fossil_stricmp(blob_str(&ans),zHash)!=0
){
X509_free(cert);
ssl_set_errmsg("SSL cert declined");
ssl_close();
blob_reset(&ans);
return 1;
}
blob_reset(&ans);
ssl_one_time_exception(pUrlData, zHash);
prompt_user("remember this exception (y/N)? ", &ans);
cReply = blob_str(&ans)[0];
if( cReply=='y' || cReply=='Y') {
db_open_config(0,0);
ssl_remember_certificate_exception(pUrlData, zHash);
}
|
| ︙ | ︙ | |||
584 585 586 587 588 589 590 |
if( strncmp("remove-exception",zCmd,nCmd)==0 ){
int i;
Blob sql;
char *zSep = "(";
db_begin_transaction();
blob_init(&sql, 0, 0);
if( g.argc==4 && find_option("all",0,0)!=0 ){
| < < > > | 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 |
if( strncmp("remove-exception",zCmd,nCmd)==0 ){
int i;
Blob sql;
char *zSep = "(";
db_begin_transaction();
blob_init(&sql, 0, 0);
if( g.argc==4 && find_option("all",0,0)!=0 ){
blob_append_sql(&sql,
"DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
"DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
"DELETE FROM config WHERE name GLOB 'cert:*';\n"
"DELETE FROM config WHERE name GLOB 'trusted:*';\n"
);
}else{
if( g.argc<4 ){
usage("remove-exception DOMAIN-NAME ...");
}
blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
for(i=3; i<g.argc; i++){
blob_append_sql(&sql,"%s'cert:%q','trust:%q'",
zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
zSep = ",";
}
blob_append_sql(&sql,");\n");
zSep = "(";
blob_append_sql(&sql,"DELETE FROM config WHERE name IN ");
for(i=3; i<g.argc; i++){
blob_append_sql(&sql,"%s'cert:%q','trusted:%q'",
zSep/*safe-for-%s*/, g.argv[i], g.argv[i]);
zSep = ",";
}
blob_append_sql(&sql,");");
}
db_unprotect(PROTECT_CONFIG);
db_exec_sql(blob_str(&sql));
db_protect_pop();
db_commit_transaction();
blob_reset(&sql);
}else
/*default*/{
fossil_fatal("unknown sub-command \"%s\".\nshould be one of:"
" remove-exception show",
zCmd);
}
#endif
}
|
Changes to src/http_transport.c.
| ︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
if( rc==0 ) transport.isOpen = 1;
#else
socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
rc = 1;
#endif
}else if( pUrlData->isFile ){
sqlite3_uint64 iRandId;
sqlite3_randomness(sizeof(iRandId), &iRandId);
transport.zOutFile = mprintf("%s-%llu-out.http",
g.zRepositoryName, iRandId);
transport.zInFile = mprintf("%s-%llu-in.http",
g.zRepositoryName, iRandId);
transport.pFile = fossil_fopen(transport.zOutFile, "wb");
if( transport.pFile==0 ){
| > > > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
if( rc==0 ) transport.isOpen = 1;
#else
socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
rc = 1;
#endif
}else if( pUrlData->isFile ){
sqlite3_uint64 iRandId;
if( !db_looks_like_a_repository(pUrlData->name) ){
fossil_fatal("not a fossil repository: \"%s\"", pUrlData->name);
}
sqlite3_randomness(sizeof(iRandId), &iRandId);
transport.zOutFile = mprintf("%s-%llu-out.http",
g.zRepositoryName, iRandId);
transport.zInFile = mprintf("%s-%llu-in.http",
g.zRepositoryName, iRandId);
transport.pFile = fossil_fopen(transport.zOutFile, "wb");
if( transport.pFile==0 ){
|
| ︙ | ︙ |
Changes to src/import.c.
| ︙ | ︙ | |||
2006 2007 2008 2009 2010 2011 2012 |
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
omitVacuum = 1;
}else{
db_begin_transaction();
fossil_print("Rebuilding repository meta-data...\n");
| | | 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 |
db_end_transaction(0);
fossil_print(" \r");
if( omitRebuild ){
omitVacuum = 1;
}else{
db_begin_transaction();
fossil_print("Rebuilding repository meta-data...\n");
rebuild_db(1, !incrFlag);
verify_cancel();
db_end_transaction(0);
}
if( !omitVacuum ){
fossil_print("Vacuuming..."); fflush(stdout);
db_multi_exec("VACUUM");
}
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
491 492 493 494 495 496 497 |
char const *zType;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
| | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
char const *zType;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(PD("name",""))
style_finish_page();
return;
}
zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
style_header("Tags and Properties");
zType = whatis_rid_type_label(rid);
if(!zType) zType = "Artifact";
|
| ︙ | ︙ | |||
625 626 627 628 629 630 631 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
| | | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(zName)
style_finish_page();
return;
}
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
zParent = db_text(0,
|
| ︙ | ︙ | |||
1946 1947 1948 1949 1950 1951 1952 |
if( iFrom<1 || iTo<iFrom ){
ajax_route_error(500, "Invalid line range from=%d, to=%d.",
iFrom, iTo);
return;
}
content_get(rid, &content);
g.isConst = 1;
| | | 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 |
if( iFrom<1 || iTo<iFrom ){
ajax_route_error(500, "Invalid line range from=%d, to=%d.",
iFrom, iTo);
return;
}
content_get(rid, &content);
g.isConst = 1;
cgi_set_content_type("application/json");
ln = 0;
while( go && ln<iFrom ){
go = blob_line(&content, &line);
ln++;
}
pOut = cgi_output_blob();
blob_append(pOut, "[\n", 2);
|
| ︙ | ︙ | |||
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 |
}
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
zMime = mimetype_from_name(zName);
style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
zName, zCI);
blob_init(&downloadName, zName, -1);
objType = OBJTYPE_CONTENT;
}else{
@ <h2>Artifact
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
if( g.perm.Setup ){
@ (%d(rid)):</h2>
| > | 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 |
}
style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
zMime = mimetype_from_name(zName);
style_submenu_element("Annotate", "%R/annotate?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Blame", "%R/blame?filename=%T&checkin=%T",
zName, zCI);
style_submenu_element("Doc", "%R/doc/%T/%T", zCI, zName);
blob_init(&downloadName, zName, -1);
objType = OBJTYPE_CONTENT;
}else{
@ <h2>Artifact
style_copy_button(1, "hash-ar", 0, 2, "%s", zUuid);
if( g.perm.Setup ){
@ (%d(rid)):</h2>
|
| ︙ | ︙ | |||
3305 3306 3307 3308 3309 3310 3311 |
@ <input type="checkbox" name="pclr" checked="checked" />
}else{
@ <input type="checkbox" name="pclr" />
}
@ Propagate color to descendants</label></div>
@ <div class='font-size-80'>Be aware that fixed background
@ colors will not interact well with all available skins.
| | | 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 |
@ <input type="checkbox" name="pclr" checked="checked" />
}else{
@ <input type="checkbox" name="pclr" />
}
@ Propagate color to descendants</label></div>
@ <div class='font-size-80'>Be aware that fixed background
@ colors will not interact well with all available skins.
@ It is recommended that Fossil be allowed to select these
@ colors automatically so that it can take the skin's
@ preferences into account.</div>
@ </td></tr>
@ <tr><th align="right" valign="top">Tags:</th>
@ <td valign="top">
@ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) />
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
2183 2184 2185 2186 2187 2188 2189 |
On large repos (e.g. fossil's) this operation is likely to take
longer than the client timeout, which will cause it to fail (but
it's sqlite3, so it'll fail gracefully).
*/
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
| | | 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 |
On large repos (e.g. fossil's) this operation is likely to take
longer than the client timeout, which will cause it to fail (but
it's sqlite3, so it'll fail gracefully).
*/
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0);
db_end_transaction(0);
return NULL;
}
}
/*
** Impl of /json/g. Requires admin/setup rights.
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
2114 2115 2116 2117 2118 2119 2120 | ); db_protect_pop(); } /* ** COMMAND: login-group* ** | | > | > > | | | > | | | | > > | | > > > > | | | | | | | | 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 |
);
db_protect_pop();
}
/*
** COMMAND: login-group*
**
** Usage: %fossil login-group ?SUBCOMMAND? ?OPTIONS?
**
** Run various subcommands to manage login-group related settings of the open
** repository or of the repository identified by the -R or --repository option.
**
** > fossil login-group
**
** Show the login-group to which the repository belongs.
**
** > fossil login-group join ?--name NAME?
**
** Add this repository to login group to which REPO belongs, or creates a
** new login group between itself and REPO if REPO does not already belong
** to a login-group. When creating a new login-group, the name of the new
** group is determined by the "--name" option.
**
** > fossil login-group leave
**
** Takes the repository out of whatever login group it is currently
** a part of.
**
** Options valid for all subcommands:
**
** -R|--repository REPO Run commands on repository REPO
**
** About Login Groups:
**
** A login-group is a set of repositories that share user credentials.
** If a user is logged into one member of the group, then that user can
** access any other group member as long as they have an entry in the USER
** table of that member. If a user changes their password using web
** interface, their password is also automatically changed in every other
** member of the login group.
*/
void login_group_command(void){
const char *zLGName;
const char *zCmd;
int nCmd;
Stmt q;
db_find_and_open_repository(0, 0);
if( g.argc>2 ){
zCmd = g.argv[2];
nCmd = (int)strlen(zCmd);
if( strncmp(zCmd,"join",nCmd)==0 && nCmd>=1 ){
const char *zNewName = find_option("name",0,1);
const char *zOther;
char *zErr = 0;
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
696 697 698 699 700 701 702 | fossil_printf_selfcheck(); fossil_limit_memory(1); /* When updating the minimum SQLite version, change the number here, ** and also MINIMUM_SQLITE_VERSION value set in ../auto.def. Take ** care that both places agree! */ | | | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
fossil_printf_selfcheck();
fossil_limit_memory(1);
/* When updating the minimum SQLite version, change the number here,
** and also MINIMUM_SQLITE_VERSION value set in ../auto.def. Take
** care that both places agree! */
if( sqlite3_libversion_number()<3037000 ){
fossil_panic("Unsuitable SQLite version %s, must be at least 3.37.0",
sqlite3_libversion());
}
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
sqlite3_config(SQLITE_CONFIG_LOG, fossil_sqlite_log, 0);
memset(&g, 0, sizeof(g));
g.now = time(0);
|
| ︙ | ︙ |
Changes to src/md5.c.
| ︙ | ︙ | |||
20 21 22 23 24 25 26 | */ #include "config.h" #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" | | > > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | */ #include "config.h" #include <string.h> #include <stdio.h> #include <sqlite3.h> #include "md5.h" #if 0 /* defined FOSSIL_ENABLE_SSL */ /* MD5 is deprecated in OpenSSL. So we have to fall back to our own ** implementation */ # include <openssl/md5.h> # define MD5Context MD5_CTX # define MD5Init MD5_Init # define MD5Update MD5_Update # define MD5Final MD5_Final |
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
305 306 307 308 309 310 311 | ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** | < < < < | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | ** a sequence of changes in a branch to be merged ** without having to merge the entire branch. ** ** --binary GLOBPATTERN Treat files that match GLOBPATTERN as binary ** and do not try to merge parallel changes. This ** option overrides the "binary-glob" setting. ** ** --cherrypick Do a cherrypick merge VERSION into the current ** checkout. A cherrypick merge pulls in the changes ** of the single check-in VERSION, rather than all ** changes back to the nearest common ancestor. ** ** -f|--force Force the merge even if it would be a no-op. ** |
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
114 115 116 117 118 119 120 | ** The aC[] array is updated and the new index into aC[] is returned. */ static int output_one_side( Blob *pOut, /* Write to this blob */ Blob *pSrc, /* The edited file that is to be copied to pOut */ int *aC, /* Array of integer triples describing the edit */ int i, /* Index in aC[] of current location in pSrc */ | | > | | | | | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
** The aC[] array is updated and the new index into aC[] is returned.
*/
static int output_one_side(
Blob *pOut, /* Write to this blob */
Blob *pSrc, /* The edited file that is to be copied to pOut */
int *aC, /* Array of integer triples describing the edit */
int i, /* Index in aC[] of current location in pSrc */
int sz, /* Number of lines in unedited source to output */
int *pLn /* Line number counter */
){
while( sz>0 ){
if( aC[i]==0 && aC[i+1]==0 && aC[i+2]==0 ) break;
if( aC[i]>=sz ){
blob_copy_lines(pOut, pSrc, sz); *pLn += sz;
aC[i] -= sz;
break;
}
blob_copy_lines(pOut, pSrc, aC[i]); *pLn += aC[i];
blob_copy_lines(pOut, pSrc, aC[i+2]); *pLn += aC[i+2];
sz -= aC[i] + aC[i+1];
i += 3;
}
return i;
}
/*
** Text of boundary markers for merge conflicts.
*/
static const char *const mergeMarker[] = {
/*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
"<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<",
"||||||| COMMON ANCESTOR content follows |||||||||||||||||||||||||",
"======= MERGED IN content follows ===============================",
">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
};
/*
** Return true if the input blob contains any CR/LF pairs on the first
** ten lines. This should be enough to detect files that use mainly CR/LF
** line endings without causing a performance impact for LF only files.
*/
|
| ︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
void ensure_line_end(Blob *pBlob, int useCrLf){
if( pBlob->nUsed<=0 ) return;
if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
if( useCrLf ) blob_append_char(pBlob, '\r');
blob_append_char(pBlob, '\n');
}
}
/*
** Do a three-way merge. Initialize pOut to contain the result.
**
** The merge is an edit against pV2. Both pV1 and pV2 have a
** common origin at pPivot. Apply the changes of pPivot ==> pV1
** to pV2.
| > > > > > > > > > > | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
void ensure_line_end(Blob *pBlob, int useCrLf){
if( pBlob->nUsed<=0 ) return;
if( pBlob->aData[pBlob->nUsed-1]!='\n' ){
if( useCrLf ) blob_append_char(pBlob, '\r');
blob_append_char(pBlob, '\n');
}
}
/*
** Write out one of the four merge-marks.
*/
void append_merge_mark(Blob *pOut, int iMark, int ln, int useCrLf){
ensure_line_end(pOut, useCrLf);
blob_append(pOut, mergeMarker[iMark], -1);
if( ln>0 ) blob_appendf(pOut, " (line %d)", ln);
ensure_line_end(pOut, useCrLf);
}
/*
** Do a three-way merge. Initialize pOut to contain the result.
**
** The merge is an edit against pV2. Both pV1 and pV2 have a
** common origin at pPivot. Apply the changes of pPivot ==> pV1
** to pV2.
|
| ︙ | ︙ | |||
194 195 196 197 198 199 200 201 202 203 204 205 206 207 | int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ int useCrLf = 0; DiffConfig DCfg; blob_zero(pOut); /* Merge results stored in pOut */ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM), ** keep it in the output. This should be secure enough not to cause ** unintended changes to the merged file and consistent with what | > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ int useCrLf = 0; int ln1, ln2, lnPivot; /* Line numbers for all files */ DiffConfig DCfg; blob_zero(pOut); /* Merge results stored in pOut */ /* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM), ** keep it in the output. This should be secure enough not to cause ** unintended changes to the merged file and consistent with what |
| ︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
/* Loop over the two edit vectors and use them to compute merged text
** which is written into pOut. i1 and i2 are multiples of 3 which are
** indices into aC1[] and aC2[] to the edit triple currently being
** processed
*/
i1 = i2 = 0;
while( i1<limit1 && i2<limit2 ){
DEBUG( printf("%d: %2d %2d %2d %d: %2d %2d %2d\n",
i1/3, aC1[i1], aC1[i1+1], aC1[i1+2],
i2/3, aC2[i2], aC2[i2+1], aC2[i2+2]); )
if( aC1[i1]>0 && aC2[i2]>0 ){
/* Output text that is unchanged in both V1 and V2 */
nCpy = min(aC1[i1], aC2[i2]);
DEBUG( printf("COPY %d\n", nCpy); )
| > | | | | | | | | | | | | | < | | | < | | | < | | | < | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
/* Loop over the two edit vectors and use them to compute merged text
** which is written into pOut. i1 and i2 are multiples of 3 which are
** indices into aC1[] and aC2[] to the edit triple currently being
** processed
*/
i1 = i2 = 0;
ln1 = ln2 = lnPivot = 1;
while( i1<limit1 && i2<limit2 ){
DEBUG( printf("%d: %2d %2d %2d %d: %2d %2d %2d\n",
i1/3, aC1[i1], aC1[i1+1], aC1[i1+2],
i2/3, aC2[i2], aC2[i2+1], aC2[i2+2]); )
if( aC1[i1]>0 && aC2[i2]>0 ){
/* Output text that is unchanged in both V1 and V2 */
nCpy = min(aC1[i1], aC2[i2]);
DEBUG( printf("COPY %d\n", nCpy); )
blob_copy_lines(pOut, pPivot, nCpy); lnPivot += nCpy;
blob_copy_lines(0, pV1, nCpy); ln1 += nCpy;
blob_copy_lines(0, pV2, nCpy); ln2 += nCpy;
aC1[i1] -= nCpy;
aC2[i2] -= nCpy;
}else
if( aC1[i1] >= aC2[i2+1] && aC1[i1]>0 && aC2[i2+1]+aC2[i2+2]>0 ){
/* Output edits to V2 that occurs within unchanged regions of V1 */
nDel = aC2[i2+1];
nIns = aC2[i2+2];
DEBUG( printf("EDIT -%d+%d left\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(0, pV1, nDel); ln1 += nDel;
blob_copy_lines(pOut, pV2, nIns); ln2 += nIns;
aC1[i1] -= nDel;
i2 += 3;
}else
if( aC2[i2] >= aC1[i1+1] && aC2[i2]>0 && aC1[i1+1]+aC1[i1+2]>0 ){
/* Output edits to V1 that occur within unchanged regions of V2 */
nDel = aC1[i1+1];
nIns = aC1[i1+2];
DEBUG( printf("EDIT -%d+%d right\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(0, pV2, nDel); ln2 += nDel;
blob_copy_lines(pOut, pV1, nIns); ln1 += nIns;
aC2[i2] -= nDel;
i1 += 3;
}else
if( sameEdit(&aC1[i1], &aC2[i2], pV1, pV2) ){
/* Output edits that are identical in both V1 and V2. */
assert( aC1[i1]==0 );
nDel = aC1[i1+1];
nIns = aC1[i1+2];
DEBUG( printf("EDIT -%d+%d both\n", nDel, nIns); )
blob_copy_lines(0, pPivot, nDel); lnPivot += nDel;
blob_copy_lines(pOut, pV1, nIns); ln1 += nIns;
blob_copy_lines(0, pV2, nIns); ln2 += nIns;
i1 += 3;
i2 += 3;
}else
{
/* We have found a region where different edits to V1 and V2 overlap.
** This is a merge conflict. Find the size of the conflict, then
** output both possible edits separated by distinctive marks.
*/
int sz = 1; /* Size of the conflict in lines */
nConflict++;
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
sz++;
}
DEBUG( printf("CONFLICT %d\n", sz); )
append_merge_mark(pOut, 0, ln1, useCrLf);
i1 = output_one_side(pOut, pV1, aC1, i1, sz, &ln1);
append_merge_mark(pOut, 1, lnPivot, useCrLf);
blob_copy_lines(pOut, pPivot, sz); lnPivot += sz;
append_merge_mark(pOut, 2, ln2, useCrLf);
i2 = output_one_side(pOut, pV2, aC2, i2, sz, &ln2);
append_merge_mark(pOut, 3, -1, useCrLf);
}
/* If we are finished with an edit triple, advance to the next
** triple.
*/
if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3;
if( i2<limit2 && aC2[i2]==0 && aC2[i2+1]==0 && aC2[i2+2]==0 ) i2+=3;
|
| ︙ | ︙ | |||
376 377 378 379 380 381 382 |
int n = blob_size(p) - len + 1;
assert( len==(int)strlen(mergeMarker[1]) );
assert( len==(int)strlen(mergeMarker[2]) );
assert( len==(int)strlen(mergeMarker[3]) );
assert( count(mergeMarker)==4 );
for(i=0; i<n; ){
for(j=0; j<4; j++){
| | | > | 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
int n = blob_size(p) - len + 1;
assert( len==(int)strlen(mergeMarker[1]) );
assert( len==(int)strlen(mergeMarker[2]) );
assert( len==(int)strlen(mergeMarker[3]) );
assert( count(mergeMarker)==4 );
for(i=0; i<n; ){
for(j=0; j<4; j++){
if( (memcmp(&z[i], mergeMarker[j], len)==0) ){
return 1;
}
}
while( i<n && z[i]!='\n' ){ i++; }
while( i<n && (z[i]=='\n' || z[i]=='\r') ){ i++; }
}
return 0;
}
|
| ︙ | ︙ |
Changes to src/piechart.c.
| ︙ | ︙ | |||
154 155 156 157 158 159 160 |
rTooSmall = 0.0;
nTooSmall = 0;
if( (pieFlags & PIE_OTHER)!=0 && nTotal>1 ){
db_prepare(&q, "SELECT sum(amt), count(*) FROM piechart WHERE amt<:amt");
db_bind_double(&q, ":amt", rTotal/OTHER_CUTOFF);
if( db_step(&q)==SQLITE_ROW ){
rTooSmall = db_column_double(&q, 0);
| | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
rTooSmall = 0.0;
nTooSmall = 0;
if( (pieFlags & PIE_OTHER)!=0 && nTotal>1 ){
db_prepare(&q, "SELECT sum(amt), count(*) FROM piechart WHERE amt<:amt");
db_bind_double(&q, ":amt", rTotal/OTHER_CUTOFF);
if( db_step(&q)==SQLITE_ROW ){
rTooSmall = db_column_double(&q, 0);
nTooSmall = db_column_int(&q, 1);
}
db_finalize(&q);
}
if( nTooSmall>1 ){
db_prepare(&q, "SELECT amt, label FROM piechart WHERE amt>=:limit"
" UNION ALL SELECT %.17g, '%d others';",
rTooSmall, nTooSmall);
|
| ︙ | ︙ |
Changes to src/pikchr.c.
| ︙ | ︙ | |||
6270 6271 6272 6273 6274 6275 6276 |
}
/*
** Round a PNum into the nearest integer
*/
static int pik_round(PNum v){
if( isnan(v) ) return 0;
| | | 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 |
}
/*
** Round a PNum into the nearest integer
*/
static int pik_round(PNum v){
if( isnan(v) ) return 0;
if( v < -2147483647 ) return (-2147483647-1);
if( v >= 2147483647 ) return 2147483647;
return (int)v;
}
/*
** Search for the variable named z[0..n-1] in:
**
|
| ︙ | ︙ |
Changes to src/pivot.c.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 |
/*
** Set a secondary file. The primary file must be set first. There
** must be at least one secondary but there can be more than one if
** desired.
*/
void pivot_set_secondary(int rid){
| | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
/*
** Set a secondary file. The primary file must be set first. There
** must be at least one secondary but there can be more than one if
** desired.
*/
void pivot_set_secondary(int rid){
/* Insert the secondary record */
db_multi_exec(
"INSERT OR IGNORE INTO aqueue(rid, mtime, pending, src)"
" SELECT %d, mtime, 1, 0 FROM event WHERE objid=%d AND type='ci'",
rid, rid
);
}
|
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
366 367 368 369 370 371 372 |
/*
** Core function to rebuild the information in the derived tables of a
** fossil repository from the blobs. This function is shared between
** 'rebuild_database' ('rebuild') and 'reconstruct_cmd'
** ('reconstruct'), both of which have to regenerate this information
** from scratch.
| < < < < < | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
/*
** Core function to rebuild the information in the derived tables of a
** fossil repository from the blobs. This function is shared between
** 'rebuild_database' ('rebuild') and 'reconstruct_cmd'
** ('reconstruct'), both of which have to regenerate this information
** from scratch.
*/
int rebuild_db(int doOut, int doClustering){
Stmt s, q;
int errCnt = 0;
int incrSize;
Blob sql;
bag_clear(&bagDone);
ttyOutput = doOut;
|
| ︙ | ︙ | |||
603 604 605 606 607 608 609 | ** --force Force the rebuild to complete even if errors are seen ** --ifneeded Only do the rebuild if it would change the schema version ** --index Always add in the full-text search index ** --noverify Skip the verification of changes to the BLOB table ** --noindex Always omit the full-text search index ** --pagesize N Set the database pagesize to N. (512..65536 and power of 2) ** --quiet Only show output if there are errors | < < < | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
** --force Force the rebuild to complete even if errors are seen
** --ifneeded Only do the rebuild if it would change the schema version
** --index Always add in the full-text search index
** --noverify Skip the verification of changes to the BLOB table
** --noindex Always omit the full-text search index
** --pagesize N Set the database pagesize to N. (512..65536 and power of 2)
** --quiet Only show output if there are errors
** --stats Show artifact statistics after rebuilding
** --vacuum Run VACUUM on the database after rebuilding
** --wal Set Write-Ahead-Log journalling mode on the database
*/
void rebuild_database(void){
int forceFlag;
int errCnt = 0;
int omitVerify;
int doClustering;
const char *zPagesize;
int newPagesize = 0;
int activateWal;
int runVacuum;
int runDeanalyze;
int runAnalyze;
int runCompress;
int showStats;
int runReindex;
int optNoIndex;
int optIndex;
int optIfNeeded;
int compressOnlyFlag;
omitVerify = find_option("noverify",0,0)!=0;
forceFlag = find_option("force","f",0)!=0;
doClustering = find_option("cluster", 0, 0)!=0;
runVacuum = find_option("vacuum",0,0)!=0;
runDeanalyze = find_option("deanalyze",0,0)!=0;
runAnalyze = find_option("analyze",0,0)!=0;
runCompress = find_option("compress",0,0)!=0;
zPagesize = find_option("pagesize",0,1);
showStats = find_option("stats",0,0)!=0;
|
| ︙ | ︙ | |||
677 678 679 680 681 682 683 |
verify_all_options();
db_begin_transaction();
db_unprotect(PROTECT_ALL);
if( !compressOnlyFlag ){
search_drop_index();
ttyOutput = 1;
| | | 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
verify_all_options();
db_begin_transaction();
db_unprotect(PROTECT_ALL);
if( !compressOnlyFlag ){
search_drop_index();
ttyOutput = 1;
errCnt = rebuild_db(1, doClustering);
reconstruct_private_table();
}
db_multi_exec(
"REPLACE INTO config(name,value,mtime) VALUES('content-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('aux-schema',%Q,now());"
"REPLACE INTO config(name,value,mtime) VALUES('rebuilt',%Q,now());",
CONTENT_SCHEMA, AUX_SCHEMA_MAX, get_version()
|
| ︙ | ︙ | |||
961 962 963 964 965 966 967 |
}
if( !bNeedRebuild ){
db_end_transaction(0);
db_unprotect(PROTECT_ALL);
db_multi_exec("VACUUM;");
db_protect_pop();
}else{
| | | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
}
if( !bNeedRebuild ){
db_end_transaction(0);
db_unprotect(PROTECT_ALL);
db_multi_exec("VACUUM;");
db_protect_pop();
}else{
rebuild_db(1, 0);
db_end_transaction(0);
}
}
/*
** Recursively read all files from the directory zPath and install
** every file read as a new artifact in the repository.
|
| ︙ | ︙ | |||
1253 1254 1255 1256 1257 1258 1259 |
db_begin_transaction();
db_initial_setup(0, 0, 0);
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
recon_read_dir(g.argv[3]);
fossil_print("\nBuilding the Fossil repository...\n");
| | | 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 |
db_begin_transaction();
db_initial_setup(0, 0, 0);
fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]);
recon_read_dir(g.argv[3]);
fossil_print("\nBuilding the Fossil repository...\n");
rebuild_db(1, 1);
/* Backwards compatibility: Mark check-ins with "+private" tags as private. */
reconstruct_private_table();
/* Newer method: Import the list of private artifacts to the PRIVATE table. */
if( fKeepPrivate ){
char *zFnDotPrivate = mprintf("%s/.private", g.argv[3]);
private_import(zFnDotPrivate);
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
870 871 872 873 874 875 876 |
if( quote ){
len += 2;
for(i=0; i<nAppend; i++){
if( zAppend[i]==quote ) len++;
}
}
| | | 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 |
if( quote ){
len += 2;
for(i=0; i<nAppend; i++){
if( zAppend[i]==quote ) len++;
}
}
if( p->z==0 || p->n+len>=p->nAlloc ){
p->nAlloc = p->nAlloc*2 + len + 20;
p->z = realloc(p->z, p->nAlloc);
if( p->z==0 ) shell_out_of_memory();
}
if( quote ){
char *zCsr = p->z+p->n;
|
| ︙ | ︙ | |||
6259 6260 6261 6262 6263 6264 6265 |
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_match_end;
}
case RE_OP_CC_EXC: {
if( c==0 ) break;
| | | | 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 |
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_match_end;
}
case RE_OP_CC_EXC: {
if( c==0 ) break;
/* fall-through */ goto re_op_cc_inc;
}
case RE_OP_CC_INC: re_op_cc_inc: {
int j = 1;
int n = pRe->aArg[x];
int hit = 0;
for(j=1; j>0 && j<n; j++){
if( pRe->aOp[x+j]==RE_OP_CC_VALUE ){
if( pRe->aArg[x+j]==c ){
hit = 1;
|
| ︙ | ︙ | |||
6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 | /* typedef sqlite3_int64 i64; */ /* typedef unsigned char u8; */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ #define MIN(a,b) ((a)<(b) ? (a) : (b)) #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) | > > > | 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 | /* typedef sqlite3_int64 i64; */ /* typedef unsigned char u8; */ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ #define MIN(a,b) ((a)<(b) ? (a) : (b)) #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) |
| ︙ | ︙ | |||
8670 8671 8672 8673 8674 8675 8676 | ** xStep() callback for the zipfile() aggregate. This can be called in ** any of the following ways: ** ** SELECT zipfile(name,data) ... ** SELECT zipfile(name,mode,mtime,data) ... ** SELECT zipfile(name,mode,mtime,data,method) ... */ | | | 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 |
** xStep() callback for the zipfile() aggregate. This can be called in
** any of the following ways:
**
** SELECT zipfile(name,data) ...
** SELECT zipfile(name,mode,mtime,data) ...
** SELECT zipfile(name,mode,mtime,data,method) ...
*/
static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
ZipfileCtx *p; /* Aggregate function context */
ZipfileEntry e; /* New entry to add to zip archive */
sqlite3_value *pName = 0;
sqlite3_value *pMode = 0;
sqlite3_value *pMtime = 0;
sqlite3_value *pData = 0;
|
| ︙ | ︙ | |||
8845 8846 8847 8848 8849 8850 8851 | } sqlite3_free(zErr); } /* ** xFinalize() callback for zipfile aggregate function. */ | | | 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 |
}
sqlite3_free(zErr);
}
/*
** xFinalize() callback for zipfile aggregate function.
*/
static void zipfileFinal(sqlite3_context *pCtx){
ZipfileCtx *p;
ZipfileEOCD eocd;
sqlite3_int64 nZip;
u8 *aZip;
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
if( p==0 ) return;
|
| ︙ | ︙ | |||
9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 | ** ************************************************************************* */ /* #include "sqlite3expert.h" */ #include <assert.h> #include <string.h> #include <stdio.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* typedef sqlite3_int64 i64; */ /* typedef sqlite3_uint64 u64; */ typedef struct IdxColumn IdxColumn; | > > > > > > > > > > > > > > > > > | 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 | ** ************************************************************************* */ /* #include "sqlite3expert.h" */ #include <assert.h> #include <string.h> #include <stdio.h> #if !defined(SQLITE_AMALGAMATION) #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #endif /* !defined(SQLITE_AMALGAMATION) */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* typedef sqlite3_int64 i64; */ /* typedef sqlite3_uint64 u64; */ typedef struct IdxColumn IdxColumn; |
| ︙ | ︙ | |||
9978 9979 9980 9981 9982 9983 9984 |
nCol++;
}
idxFinalize(&rc, p1);
if( rc!=SQLITE_OK ){
sqlite3_free(pNew);
pNew = 0;
| | | | 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 |
nCol++;
}
idxFinalize(&rc, p1);
if( rc!=SQLITE_OK ){
sqlite3_free(pNew);
pNew = 0;
}else if( ALWAYS(pNew!=0) ){
pNew->zName = pCsr;
if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
}
*ppOut = pNew;
return rc;
}
/*
|
| ︙ | ︙ | |||
10388 10389 10390 10391 10392 10393 10394 | /* ** This function is called after candidate indexes have been created. It ** runs all the queries to see which indexes they prefer, and populates ** IdxStatement.zIdx and IdxStatement.zEQP with the results. */ | | | 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 |
/*
** This function is called after candidate indexes have been created. It
** runs all the queries to see which indexes they prefer, and populates
** IdxStatement.zIdx and IdxStatement.zEQP with the results.
*/
static int idxFindIndexes(
sqlite3expert *p,
char **pzErr /* OUT: Error message (sqlite3_malloc) */
){
IdxStatement *pStmt;
sqlite3 *dbm = p->dbm;
int rc = SQLITE_OK;
|
| ︙ | ︙ | |||
12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 |
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 11 /* Pretty-print schemas */
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json 13 /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table 15 /* MySQL-style table formatting */
#define MODE_Box 16 /* Unicode box-drawing characters */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"quote",
"tcl",
"csv",
"explain",
"ascii",
"prettyprint",
"eqp",
"json",
"markdown",
"table",
| > > | > > | 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 |
#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
#define MODE_Pretty 11 /* Pretty-print schemas */
#define MODE_EQP 12 /* Converts EXPLAIN QUERY PLAN output into a graph */
#define MODE_Json 13 /* Output JSON */
#define MODE_Markdown 14 /* Markdown formatting */
#define MODE_Table 15 /* MySQL-style table formatting */
#define MODE_Box 16 /* Unicode box-drawing characters */
#define MODE_Count 17 /* Output only a count of the rows of output */
#define MODE_Off 18 /* No query output shown */
static const char *modeDescr[] = {
"line",
"column",
"list",
"semi",
"html",
"insert",
"quote",
"tcl",
"csv",
"explain",
"ascii",
"prettyprint",
"eqp",
"json",
"markdown",
"table",
"box",
"count",
"off"
};
/*
** These are the column/row/line separators used by the various
** import/export modes.
*/
#define SEP_Column "|"
|
| ︙ | ︙ | |||
12796 12797 12798 12799 12800 12801 12802 |
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
utf8_printf(out,"%s",p->nullValue);
}else{
| | < | < < | | 12820 12821 12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 |
** is only issued if bSep is true.
*/
static void output_csv(ShellState *p, const char *z, int bSep){
FILE *out = p->out;
if( z==0 ){
utf8_printf(out,"%s",p->nullValue);
}else{
unsigned i;
for(i=0; z[i]; i++){
if( needCsvQuote[((unsigned char*)z)[i]] ){
i = 0;
break;
}
}
if( i==0 || strstr(z, p->colSeparator)!=0 ){
char *zQuoted = sqlite3_mprintf("\"%w\"", z);
utf8_printf(out, "%s", zQuoted);
sqlite3_free(zQuoted);
}else{
utf8_printf(out, "%s", z);
}
}
|
| ︙ | ︙ | |||
13130 13131 13132 13133 13134 13135 13136 13137 13138 13139 13140 13141 13142 13143 |
int *aiType /* Column types. Might be NULL */
){
int i;
ShellState *p = (ShellState*)pArg;
if( azArg==0 ) return 0;
switch( p->cMode ){
case MODE_Line: {
int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int len = strlen30(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
| > > > > | 13151 13152 13153 13154 13155 13156 13157 13158 13159 13160 13161 13162 13163 13164 13165 13166 13167 13168 |
int *aiType /* Column types. Might be NULL */
){
int i;
ShellState *p = (ShellState*)pArg;
if( azArg==0 ) return 0;
switch( p->cMode ){
case MODE_Count:
case MODE_Off: {
break;
}
case MODE_Line: {
int w = 5;
if( azArg==0 ) break;
for(i=0; i<nArg; i++){
int len = strlen30(azCol[i] ? azCol[i] : "");
if( len>w ) w = len;
}
|
| ︙ | ︙ | |||
13640 13641 13642 13643 13644 13645 13646 |
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
}
return rc;
}
/*
| | | > > < < | > | < < | 13665 13666 13667 13668 13669 13670 13671 13672 13673 13674 13675 13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687 13688 |
sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
}
return rc;
}
/*
** Allocate space and save off string indicating current error.
*/
static char *save_err_msg(
sqlite3 *db, /* Database to query */
const char *zWhen, /* Qualifier (format) wrapper */
int rc /* Error code returned from API */
){
if( zWhen==0 )
zWhen = "%s (%d)";
return sqlite3_mprintf(zWhen, sqlite3_errmsg(db), rc);
}
#ifdef __linux__
/*
** Attempt to display I/O stats on Linux using /proc/PID/io
*/
static void displayLinuxIoStats(FILE *out){
|
| ︙ | ︙ | |||
13828 13829 13830 13831 13832 13833 13834 13835 13836 13837 13838 13839 13840 13841 13842 13843 13844 13845 13846 13847 13848 |
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
iCur);
}
if( pArg->pStmt ){
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
bReset);
raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
| > > > > > > > | 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868 13869 13870 13871 13872 13873 13874 13875 13876 13877 13878 13879 |
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
iCur);
}
if( pArg->pStmt ){
int iHit, iMiss;
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
bReset);
raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
if( iHit || iMiss ){
raw_printf(pArg->out, "Bloom filter bypass taken: %d/%d\n",
iHit, iHit+iMiss);
}
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
|
| ︙ | ︙ | |||
14341 14342 14343 14344 14345 14346 14347 14348 14349 14350 14351 14352 14353 14354 |
** Run a prepared statement
*/
static void exec_prepared_stmt(
ShellState *pArg, /* Pointer to ShellState */
sqlite3_stmt *pStmt /* Statment to run */
){
int rc;
if( pArg->cMode==MODE_Column
|| pArg->cMode==MODE_Table
|| pArg->cMode==MODE_Box
|| pArg->cMode==MODE_Markdown
){
exec_prepared_stmt_columnar(pArg, pStmt);
| > | 14372 14373 14374 14375 14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 |
** Run a prepared statement
*/
static void exec_prepared_stmt(
ShellState *pArg, /* Pointer to ShellState */
sqlite3_stmt *pStmt /* Statment to run */
){
int rc;
sqlite3_uint64 nRow = 0;
if( pArg->cMode==MODE_Column
|| pArg->cMode==MODE_Table
|| pArg->cMode==MODE_Box
|| pArg->cMode==MODE_Markdown
){
exec_prepared_stmt_columnar(pArg, pStmt);
|
| ︙ | ︙ | |||
14373 14374 14375 14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 |
int i, x;
assert(sizeof(int) <= sizeof(char *));
/* save off ptrs to column names */
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
do{
/* extract the data and data types */
for(i=0; i<nCol; i++){
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
azVals[i] = "";
}else{
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
| > | 14405 14406 14407 14408 14409 14410 14411 14412 14413 14414 14415 14416 14417 14418 14419 |
int i, x;
assert(sizeof(int) <= sizeof(char *));
/* save off ptrs to column names */
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
do{
nRow++;
/* extract the data and data types */
for(i=0; i<nCol; i++){
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
azVals[i] = "";
}else{
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
| ︙ | ︙ | |||
14400 14401 14402 14403 14404 14405 14406 14407 14408 14409 14410 14411 14412 14413 |
rc = sqlite3_step(pStmt);
}
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg->cMode==MODE_Json ){
fputs("]\n", pArg->out);
}
}
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
| > > | 14433 14434 14435 14436 14437 14438 14439 14440 14441 14442 14443 14444 14445 14446 14447 14448 |
rc = sqlite3_step(pStmt);
}
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg->cMode==MODE_Json ){
fputs("]\n", pArg->out);
}else if( pArg->cMode==MODE_Count ){
printf("%llu row%s\n", nRow, nRow!=1 ? "s" : "");
}
}
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
|
| ︙ | ︙ | |||
14572 14573 14574 14575 14576 14577 14578 |
#endif
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
if( SQLITE_OK != rc ){
if( pzErrMsg ){
| | | 14607 14608 14609 14610 14611 14612 14613 14614 14615 14616 14617 14618 14619 14620 14621 |
#endif
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
if( SQLITE_OK != rc ){
if( pzErrMsg ){
*pzErrMsg = save_err_msg(db, "in prepare, %s (%d)", rc);
}
}else{
if( !pStmt ){
/* this happens for a comment or white-space */
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
continue;
|
| ︙ | ︙ | |||
14686 14687 14688 14689 14690 14691 14692 |
** next statement to execute. */
rc2 = sqlite3_finalize(pStmt);
if( rc!=SQLITE_NOMEM ) rc = rc2;
if( rc==SQLITE_OK ){
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
}else if( pzErrMsg ){
| | | 14721 14722 14723 14724 14725 14726 14727 14728 14729 14730 14731 14732 14733 14734 14735 |
** next statement to execute. */
rc2 = sqlite3_finalize(pStmt);
if( rc!=SQLITE_NOMEM ) rc = rc2;
if( rc==SQLITE_OK ){
zSql = zLeftover;
while( IsSpace(zSql[0]) ) zSql++;
}else if( pzErrMsg ){
*pzErrMsg = save_err_msg(db, "stepping, %s (%d)", rc);
}
/* clear saved stmt handle */
if( pArg ){
pArg->pStmt = NULL;
}
}
|
| ︙ | ︙ | |||
15000 15001 15002 15003 15004 15005 15006 15007 15008 15009 15010 15011 15012 15013 15014 15015 15016 15017 15018 15019 15020 |
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
" http://sqlite.org/cli.html#sqlite_archive_support",
| > > | 15035 15036 15037 15038 15039 15040 15041 15042 15043 15044 15045 15046 15047 15048 15049 15050 15051 15052 15053 15054 15055 15056 15057 |
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
".archive ... Manage SQL archives",
" Each command must have exactly one of the following options:",
" -c, --create Create a new archive",
" -u, --update Add or update files with changed mtime",
" -i, --insert Like -u but always add even if unchanged",
" -r, --remove Remove files from archive",
" -t, --list List contents of archive",
" -x, --extract Extract files from archive",
" Optional arguments:",
" -v, --verbose Print each filename as it is processed",
" -f FILE, --file FILE Use archive FILE (default is current db)",
" -a FILE, --append FILE Open FILE using the apndvfs VFS",
" -C DIR, --directory DIR Read/extract files from directory DIR",
" -g, --glob Use glob matching for names in archive",
" -n, --dryrun Show the SQL that would have occurred",
" Examples:",
" .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
" .ar -tf ARCHIVE # List members of ARCHIVE",
" .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
" See also:",
" http://sqlite.org/cli.html#sqlite_archive_support",
|
| ︙ | ︙ | |||
17167 17168 17169 17170 17171 17172 17173 17174 17175 17176 17177 17178 17179 17180 |
typedef struct ArCommand ArCommand;
struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
const char *zDir; /* --directory argument, or NULL */
char **azArg; /* Array of command arguments */
ShellState *p; /* Shell state */
| > | 17204 17205 17206 17207 17208 17209 17210 17211 17212 17213 17214 17215 17216 17217 17218 |
typedef struct ArCommand ArCommand;
struct ArCommand {
u8 eCmd; /* An AR_CMD_* value */
u8 bVerbose; /* True if --verbose */
u8 bZip; /* True if the archive is a ZIP */
u8 bDryRun; /* True if --dry-run */
u8 bAppend; /* True if --append */
u8 bGlob; /* True if --glob */
u8 fromCmdLine; /* Run from -A instead of .archive */
int nArg; /* Number of command arguments */
char *zSrcTable; /* "sqlar", "zipfile($file)" or "zip" */
const char *zFile; /* --file argument, or NULL */
const char *zDir; /* --directory argument, or NULL */
char **azArg; /* Array of command arguments */
ShellState *p; /* Shell state */
|
| ︙ | ︙ | |||
17214 17215 17216 17217 17218 17219 17220 17221 17222 17223 17224 | */ #define AR_CMD_CREATE 1 #define AR_CMD_UPDATE 2 #define AR_CMD_INSERT 3 #define AR_CMD_EXTRACT 4 #define AR_CMD_LIST 5 #define AR_CMD_HELP 6 /* ** Other (non-command) switches. */ | > | | | | | > > > > > | 17252 17253 17254 17255 17256 17257 17258 17259 17260 17261 17262 17263 17264 17265 17266 17267 17268 17269 17270 17271 17272 17273 17274 17275 17276 17277 17278 17279 17280 17281 17282 17283 17284 17285 17286 17287 17288 17289 17290 17291 17292 17293 17294 17295 17296 17297 |
*/
#define AR_CMD_CREATE 1
#define AR_CMD_UPDATE 2
#define AR_CMD_INSERT 3
#define AR_CMD_EXTRACT 4
#define AR_CMD_LIST 5
#define AR_CMD_HELP 6
#define AR_CMD_REMOVE 7
/*
** Other (non-command) switches.
*/
#define AR_SWITCH_VERBOSE 8
#define AR_SWITCH_FILE 9
#define AR_SWITCH_DIRECTORY 10
#define AR_SWITCH_APPEND 11
#define AR_SWITCH_DRYRUN 12
#define AR_SWITCH_GLOB 13
static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
switch( eSwitch ){
case AR_CMD_CREATE:
case AR_CMD_EXTRACT:
case AR_CMD_LIST:
case AR_CMD_REMOVE:
case AR_CMD_UPDATE:
case AR_CMD_INSERT:
case AR_CMD_HELP:
if( pAr->eCmd ){
return arErrorMsg(pAr, "multiple command options");
}
pAr->eCmd = eSwitch;
break;
case AR_SWITCH_DRYRUN:
pAr->bDryRun = 1;
break;
case AR_SWITCH_GLOB:
pAr->bGlob = 1;
break;
case AR_SWITCH_VERBOSE:
pAr->bVerbose = 1;
break;
case AR_SWITCH_APPEND:
pAr->bAppend = 1;
/* Fall thru into --file */
|
| ︙ | ︙ | |||
17279 17280 17281 17282 17283 17284 17285 17286 17287 17288 17289 17290 17291 17292 17293 17294 17295 17296 17297 17298 17299 |
u8 eSwitch;
u8 bArg;
} aSwitch[] = {
{ "create", 'c', AR_CMD_CREATE, 0 },
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
{ "file", 'f', AR_SWITCH_FILE, 1 },
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
| > > | 17323 17324 17325 17326 17327 17328 17329 17330 17331 17332 17333 17334 17335 17336 17337 17338 17339 17340 17341 17342 17343 17344 17345 |
u8 eSwitch;
u8 bArg;
} aSwitch[] = {
{ "create", 'c', AR_CMD_CREATE, 0 },
{ "extract", 'x', AR_CMD_EXTRACT, 0 },
{ "insert", 'i', AR_CMD_INSERT, 0 },
{ "list", 't', AR_CMD_LIST, 0 },
{ "remove", 'r', AR_CMD_REMOVE, 0 },
{ "update", 'u', AR_CMD_UPDATE, 0 },
{ "help", 'h', AR_CMD_HELP, 0 },
{ "verbose", 'v', AR_SWITCH_VERBOSE, 0 },
{ "file", 'f', AR_SWITCH_FILE, 1 },
{ "append", 'a', AR_SWITCH_APPEND, 1 },
{ "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
{ "dryrun", 'n', AR_SWITCH_DRYRUN, 0 },
{ "glob", 'g', AR_SWITCH_GLOB, 0 },
};
int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
|
| ︙ | ︙ | |||
17402 17403 17404 17405 17406 17407 17408 | } return SQLITE_OK; } /* ** This function assumes that all arguments within the ArCommand.azArg[] | | | | | | > > > > > | < < < | 17448 17449 17450 17451 17452 17453 17454 17455 17456 17457 17458 17459 17460 17461 17462 17463 17464 17465 17466 17467 17468 17469 17470 17471 17472 17473 17474 17475 17476 17477 17478 17479 17480 17481 17482 17483 |
}
return SQLITE_OK;
}
/*
** This function assumes that all arguments within the ArCommand.azArg[]
** array refer to archive members, as for the --extract, --list or --remove
** commands. It checks that each of them are "present". If any specified
** file is not present in the archive, an error is printed to stderr and an
** error code returned. Otherwise, if all specified arguments are present
** in the archive, SQLITE_OK is returned. Here, "present" means either an
** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
** when pAr->bGlob is true.
**
** This function strips any trailing '/' characters from each argument.
** This is consistent with the way the [tar] command seems to work on
** Linux.
*/
static int arCheckEntries(ArCommand *pAr){
int rc = SQLITE_OK;
if( pAr->nArg ){
int i, j;
sqlite3_stmt *pTest = 0;
const char *zSel = (pAr->bGlob)
? "SELECT name FROM %s WHERE glob($name,name)"
: "SELECT name FROM %s WHERE name=$name";
shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
j = sqlite3_bind_parameter_index(pTest, "$name");
for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
char *z = pAr->azArg[i];
int n = strlen30(z);
int bOk = 0;
while( n>0 && z[n-1]=='/' ) n--;
z[n] = '\0';
|
| ︙ | ︙ | |||
17449 17450 17451 17452 17453 17454 17455 | } /* ** Format a WHERE clause that can be used against the "sqlar" table to ** identify all archive members that match the command arguments held ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning. ** The caller is responsible for eventually calling sqlite3_free() on | | > | > | | | 17497 17498 17499 17500 17501 17502 17503 17504 17505 17506 17507 17508 17509 17510 17511 17512 17513 17514 17515 17516 17517 17518 17519 17520 17521 17522 17523 17524 17525 17526 17527 17528 17529 17530 17531 |
}
/*
** Format a WHERE clause that can be used against the "sqlar" table to
** identify all archive members that match the command arguments held
** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
** The caller is responsible for eventually calling sqlite3_free() on
** any non-NULL (*pzWhere) value. Here, "match" means strict equality
** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
*/
static void arWhereClause(
int *pRc,
ArCommand *pAr,
char **pzWhere /* OUT: New WHERE clause */
){
char *zWhere = 0;
const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
if( *pRc==SQLITE_OK ){
if( pAr->nArg==0 ){
zWhere = sqlite3_mprintf("1");
}else{
int i;
const char *zSep = "";
for(i=0; i<pAr->nArg; i++){
const char *z = pAr->azArg[i];
zWhere = sqlite3_mprintf(
"%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
);
if( zWhere==0 ){
*pRc = SQLITE_NOMEM;
break;
}
zSep = " OR ";
}
|
| ︙ | ︙ | |||
17520 17521 17522 17523 17524 17525 17526 17527 17528 17529 17530 17531 17532 17533 |
}
}
shellFinalize(&rc, pSql);
sqlite3_free(zWhere);
return rc;
}
/*
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
const char *zSql1 =
"SELECT "
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 17570 17571 17572 17573 17574 17575 17576 17577 17578 17579 17580 17581 17582 17583 17584 17585 17586 17587 17588 17589 17590 17591 17592 17593 17594 17595 17596 17597 17598 17599 17600 17601 17602 17603 17604 17605 17606 17607 17608 17609 17610 17611 17612 17613 17614 17615 17616 17617 17618 17619 17620 17621 17622 17623 17624 |
}
}
shellFinalize(&rc, pSql);
sqlite3_free(zWhere);
return rc;
}
/*
** Implementation of .ar "Remove" command.
*/
static int arRemoveCommand(ArCommand *pAr){
int rc = 0;
char *zSql = 0;
char *zWhere = 0;
if( pAr->nArg ){
/* Verify that args actually exist within the archive before proceeding.
** And formulate a WHERE clause to match them. */
rc = arCheckEntries(pAr);
arWhereClause(&rc, pAr, &zWhere);
}
if( rc==SQLITE_OK ){
zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
pAr->zSrcTable, zWhere);
if( pAr->bDryRun ){
utf8_printf(pAr->p->out, "%s\n", zSql);
}else{
char *zErr = 0;
rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
}else{
rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
}
}
if( zErr ){
utf8_printf(stdout, "ERROR: %s\n", zErr);
sqlite3_free(zErr);
}
}
}
sqlite3_free(zWhere);
sqlite3_free(zSql);
return rc;
}
/*
** Implementation of .ar "eXtract" command.
*/
static int arExtractCommand(ArCommand *pAr){
const char *zSql1 =
"SELECT "
|
| ︙ | ︙ | |||
17773 17774 17775 17776 17777 17778 17779 |
}
}
cmd.bZip = 1;
}else if( cmd.zFile ){
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
| | | 17864 17865 17866 17867 17868 17869 17870 17871 17872 17873 17874 17875 17876 17877 17878 |
}
}
cmd.bZip = 1;
}else if( cmd.zFile ){
int flags;
if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
|| cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
}else{
flags = SQLITE_OPEN_READONLY;
}
cmd.db = 0;
if( cmd.bDryRun ){
utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
|
| ︙ | ︙ | |||
17828 17829 17830 17831 17832 17833 17834 17835 17836 17837 17838 17839 17840 17841 |
case AR_CMD_HELP:
arUsage(pState->out);
break;
case AR_CMD_INSERT:
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
break;
}
}
| > > > > | 17919 17920 17921 17922 17923 17924 17925 17926 17927 17928 17929 17930 17931 17932 17933 17934 17935 17936 |
case AR_CMD_HELP:
arUsage(pState->out);
break;
case AR_CMD_INSERT:
rc = arCreateOrUpdateCommand(&cmd, 1, 0);
break;
case AR_CMD_REMOVE:
rc = arRemoveCommand(&cmd);
break;
default:
assert( cmd.eCmd==AR_CMD_UPDATE );
rc = arCreateOrUpdateCommand(&cmd, 1, 1);
break;
}
}
|
| ︙ | ︙ | |||
19317 19318 19319 19320 19321 19322 19323 19324 19325 19326 19327 19328 19329 19330 |
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
for(i=1; i<nArg; i++){
char *z = azArg[i];
| > > > > > | 19412 19413 19414 19415 19416 19417 19418 19419 19420 19421 19422 19423 19424 19425 19426 19427 19428 19429 19430 |
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
int eVerbose = 0; /* Larger for more console output */
int nSkip = 0; /* Initial lines to skip */
int useOutputMode = 1; /* Use output mode to determine separators */
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
for(i=1; i<nArg; i++){
char *z = azArg[i];
|
| ︙ | ︙ | |||
19426 19427 19428 19429 19430 19431 19432 19433 19434 19435 19436 19437 19438 19439 |
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
rc = 1;
goto meta_command_exit;
}
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;
utf8_printf(p->out, "Column separator ");
| > | 19526 19527 19528 19529 19530 19531 19532 19533 19534 19535 19536 19537 19538 19539 19540 |
}else{
sCtx.in = fopen(sCtx.zFile, "rb");
sCtx.xCloser = fclose;
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
rc = 1;
import_cleanup(&sCtx);
goto meta_command_exit;
}
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
zSep[0] = sCtx.cColSep;
utf8_printf(p->out, "Column separator ");
|
| ︙ | ︙ | |||
19844 19845 19846 19847 19848 19849 19850 19851 19852 19853 19854 19855 19856 19857 |
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
p->mode = MODE_Markdown;
}else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
p->mode = MODE_Table;
}else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
p->mode = MODE_Box;
}else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
p->mode = MODE_Json;
}else if( nArg==1 ){
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
}else{
raw_printf(stderr, "Error: mode should be one of: "
"ascii box column csv html insert json line list markdown "
| > > > > | 19945 19946 19947 19948 19949 19950 19951 19952 19953 19954 19955 19956 19957 19958 19959 19960 19961 19962 |
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
}else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
p->mode = MODE_Markdown;
}else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
p->mode = MODE_Table;
}else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
p->mode = MODE_Box;
}else if( c2=='c' && strncmp(azArg[1],"count",n2)==0 ){
p->mode = MODE_Count;
}else if( c2=='o' && strncmp(azArg[1],"off",n2)==0 ){
p->mode = MODE_Off;
}else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
p->mode = MODE_Json;
}else if( nArg==1 ){
raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
}else{
raw_printf(stderr, "Error: mode should be one of: "
"ascii box column csv html insert json line list markdown "
|
| ︙ | ︙ | |||
19913 19914 19915 19916 19917 19918 19919 |
}else
#endif /* SQLITE_DEBUG */
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
| < < < < < < < | | < | | | < < | | > > > > > > > > > > > > | 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 20041 20042 20043 20044 20045 20046 20047 20048 20049 20050 20051 20052 20053 20054 20055 20056 20057 20058 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 |
}else
#endif /* SQLITE_DEBUG */
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
char *zNewFilename = 0; /* Name of the database file to open */
int iName = 1; /* Index in azArg[] of the filename */
int newFlag = 0; /* True to delete file before opening */
int openMode = SHELL_OPEN_UNSPEC;
/* Check for command-line arguments */
for(iName=1; iName<nArg; iName++){
const char *z = azArg[iName];
if( optionMatch(z,"new") ){
newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
}else if( optionMatch(z, "zip") ){
openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( optionMatch(z, "append") ){
openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
openMode = SHELL_OPEN_HEXDB;
}else if( optionMatch(z, "maxsize") && iName+1<nArg ){
p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
goto meta_command_exit;
}else if( zNewFilename ){
utf8_printf(stderr, "extra argument: \"%s\"\n", z);
rc = 1;
goto meta_command_exit;
}else{
zNewFilename = sqlite3_mprintf("%s", z);
}
}
/* Close the existing database */
session_close_all(p, -1);
close_db(p->db);
p->db = 0;
p->pAuxDb->zDbFilename = 0;
sqlite3_free(p->pAuxDb->zFreeOnClose);
p->pAuxDb->zFreeOnClose = 0;
p->openMode = openMode;
p->openFlags = 0;
p->szMax = 0;
/* If a filename is specified, try to open it first */
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag && !p->bSafeMode ) shellDeleteFile(zNewFilename);
if( p->bSafeMode
&& p->openMode!=SHELL_OPEN_HEXDB
&& zNewFilename
&& strcmp(zNewFilename,":memory:")!=0
|
| ︙ | ︙ | |||
21178 21179 21180 21181 21182 21183 21184 21185 21186 |
}else
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
| > | | | | | | | | | | | | | | | | | | | | | 21285 21286 21287 21288 21289 21290 21291 21292 21293 21294 21295 21296 21297 21298 21299 21300 21301 21302 21303 21304 21305 21306 21307 21308 21309 21310 21311 21312 21313 21314 21315 21316 21317 21318 21319 21320 21321 21322 21323 |
}else
#ifndef SQLITE_UNTESTABLE
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
int ctrlCode; /* Integer code for that option */
int unSafe; /* Not valid for --safe mode */
const char *zUsage; /* Usage notes */
} aCtrl[] = {
{ "always", SQLITE_TESTCTRL_ALWAYS, 1, "BOOLEAN" },
{ "assert", SQLITE_TESTCTRL_ASSERT, 1, "BOOLEAN" },
/*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, "" },*/
/*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, 1, "" },*/
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, 0, "" },
{ "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, 1,"" },*/
{ "imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
{ "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" },
#ifdef YYCOVERAGE
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE,0,"" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE,0, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, 0, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, 0, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, 0, "" },
{ "sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" },
{ "tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" },
};
int testctrl = -1;
int iCtrl = -1;
int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */
int isOk = 0;
int i, n2;
const char *zCmd = 0;
|
| ︙ | ︙ | |||
21249 21250 21251 21252 21253 21254 21255 21256 21257 21258 21259 21260 21261 21262 |
goto meta_command_exit;
}
}
}
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){
unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
| > > > > > | 21357 21358 21359 21360 21361 21362 21363 21364 21365 21366 21367 21368 21369 21370 21371 21372 21373 21374 21375 |
goto meta_command_exit;
}
}
}
if( testctrl<0 ){
utf8_printf(stderr,"Error: unknown test-control: %s\n"
"Use \".testctrl --help\" for help\n", zCmd);
}else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
utf8_printf(stderr,
"line %d: \".testctrl %s\" may not be used in safe mode\n",
p->lineno, aCtrl[iCtrl].zCtrlName);
exit(1);
}else{
switch(testctrl){
/* sqlite3_test_control(int, db, int) */
case SQLITE_TESTCTRL_OPTIMIZATIONS:
if( nArg==3 ){
unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
|
| ︙ | ︙ |
Changes to src/shun.c.
| ︙ | ︙ | |||
58 59 60 61 62 63 64 |
login_needed(0);
return;
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
| | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
login_needed(0);
return;
}
if( P("rebuild") ){
db_close(1);
db_open_repository(g.zRepositoryName);
db_begin_transaction();
rebuild_db(0, 0);
admin_log("Rebuilt database.");
db_end_transaction(0);
}
if( zUuid ){
char *p;
int i = 0;
int j = 0;
|
| ︙ | ︙ |
Changes to src/sqlite3.c.
1 2 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite | | | 1 2 3 4 5 6 7 8 9 10 | /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite ** version 3.38.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements ** of 5% or more are commonly seen when SQLite is compiled as a single ** translation unit. ** ** This file is all you need to compile SQLite. To use SQLite in other |
| ︙ | ︙ | |||
448 449 450 451 452 453 454 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 #define SQLITE_SOURCE_ID "2021-12-09 20:06:18 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
841 842 843 844 845 846 847 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) | < | 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) |
| ︙ | ︙ | |||
877 878 879 880 881 882 883 884 885 886 887 888 889 890 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ | > > > > > > > > > > > > > | 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ** ** Only those flags marked as "Ok for sqlite3_open_v2()" may be ** used as the third argument to the [sqlite3_open_v2()] interface. ** The other flags have historically been ignored by sqlite3_open_v2(), ** though future versions of SQLite might change so that an error is ** raised if any of the disallowed bits are passed into sqlite3_open_v2(). ** Applications should not depend on the historical behavior. ** ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into ** [sqlite3_open_v2()] has historically be a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| ︙ | ︙ | |||
899 900 901 902 903 904 905 906 907 908 909 910 911 912 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* | > | 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* |
| ︙ | ︙ | |||
3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> | > > > > > > > > < < < < < < | > > > > > > > > | 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt> ** <dd>The database connection comes up in "extended result code mode". ** In other words, the database behaves has if ** [sqlite3_extended_result_codes(db,1)] where called on the database ** connection as soon as the connection is created. In addition to setting ** the extended result code mode, this flag also causes [sqlite3_open_v2()] ** to return an extended result code.</dd> ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. Historic versions of SQLite ** have silently ignored surplus bits in the flags parameter to ** sqlite3_open_v2(), however that behavior might not be carried through ** into future versions of SQLite and so applications should not rely ** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op ** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause ** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE ** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not ** by sqlite3_open_v2(). ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database |
| ︙ | ︙ | |||
6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 | ** ^The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 |
** ^The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
**
** See also the [sqlite3_update_hook()] interface.
*/
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
** function C that is invoked prior to each autovacuum of the database
** file. ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively. The callback should
** return the number of free pages that should be removed by the
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface. If it does, bad
** things may happen, including segmentation faults and corrupt database
** files. The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter. ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection. ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled. The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong. The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages. So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** unsigned int demonstration_autovac_pages_callback(
** void *pClientData,
** const char *zSchema,
** unsigned int nDbPage,
** unsigned int nFreePage,
** unsigned int nBytePerPage
** ){
** return nFreePage;
** }
** </pre></blockquote>
*/
SQLITE_API int sqlite3_autovacuum_pages(
sqlite3 *db,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*,
void(*)(void*)
);
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
|
| ︙ | ︙ | |||
8157 8158 8159 8160 8161 8162 8163 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 | > | | 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 #define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, |
| ︙ | ︙ | |||
8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of | > > > > > > > > > > > > | 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_FILTER_MISS]] ** [[SQLITE_STMTSTATUS_FILTER HIT]] ** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br> ** SQLITE_STMTSTATUS_FILTER_MISS</dt> ** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join ** step was bypassed because a Bloom filter returned not-found. The ** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of ** times that the Bloom filter returned a find, and thus the join step ** had to be processed as normal. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_FILTER_MISS 7 #define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of |
| ︙ | ︙ | |||
13158 13159 13160 13161 13162 13163 13164 | ** to help ensure adequate test coverage in places where simple ** condition/decision coverage is inadequate. For example, testcase() ** can be used to make sure boundary values are tested. For ** bitmask tests, testcase() can be used to make sure each bit ** is significant and used at least once. On switch statements ** where multiple cases go to the same block of code, testcase() ** can insure that all cases are evaluated. | < | > | > | | 13260 13261 13262 13263 13264 13265 13266 13267 13268 13269 13270 13271 13272 13273 13274 13275 13276 13277 13278 13279 |
** to help ensure adequate test coverage in places where simple
** condition/decision coverage is inadequate. For example, testcase()
** can be used to make sure boundary values are tested. For
** bitmask tests, testcase() can be used to make sure each bit
** is significant and used at least once. On switch statements
** where multiple cases go to the same block of code, testcase()
** can insure that all cases are evaluated.
*/
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
# ifndef SQLITE_AMALGAMATION
extern unsigned int sqlite3CoverageCounter;
# endif
# define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; }
#else
# define testcase(X)
#endif
/*
** The TESTONLY macro is used to enclose variable declarations or
** other bits of code that are needed to support the arguments
|
| ︙ | ︙ | |||
13192 13193 13194 13195 13196 13197 13198 13199 13200 13201 13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212 13213 | */ #ifndef NDEBUG # define VVA_ONLY(X) X #else # define VVA_ONLY(X) #endif /* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience ** of SQLite to unexpected behavior - to make the code "self-healing" ** or "ductile" rather than being "brittle" and crashing at the first ** hint of unplanned behavior. ** ** In other words, ALWAYS and NEVER are added for defensive code. ** ** When doing coverage testing ALWAYS and NEVER are hard-coded to ** be true and false so that the unreachable code they specify will ** not be counted as untested code. */ | > > > > > > > > | < < < < < < < < < < < < < < < < < < < < | 13295 13296 13297 13298 13299 13300 13301 13302 13303 13304 13305 13306 13307 13308 13309 13310 13311 13312 13313 13314 13315 13316 13317 13318 13319 13320 13321 13322 13323 13324 13325 13326 13327 13328 13329 13330 13331 13332 13333 13334 13335 13336 13337 13338 13339 13340 13341 13342 | */ #ifndef NDEBUG # define VVA_ONLY(X) X #else # define VVA_ONLY(X) #endif /* ** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage ** and mutation testing */ #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif /* ** The ALWAYS and NEVER macros surround boolean expressions which ** are intended to always be true or false, respectively. Such ** expressions could be omitted from the code completely. But they ** are included in a few cases in order to enhance the resilience ** of SQLite to unexpected behavior - to make the code "self-healing" ** or "ductile" rather than being "brittle" and crashing at the first ** hint of unplanned behavior. ** ** In other words, ALWAYS and NEVER are added for defensive code. ** ** When doing coverage testing ALWAYS and NEVER are hard-coded to ** be true and false so that the unreachable code they specify will ** not be counted as untested code. */ #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif /* ** Some conditionals are optimizations only. In other words, if the ** conditionals are replaced with a constant 1 (true) or 0 (false) then ** the correct answer is still obtained, though perhaps not as quickly. ** ** The following macros mark these optimizations conditionals. */ |
| ︙ | ︙ | |||
13420 13421 13422 13423 13424 13425 13426 | #define sqliteHashData(E) ((E)->data) /* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ | | | 13511 13512 13513 13514 13515 13516 13517 13518 13519 13520 13521 13522 13523 13524 13525 | #define sqliteHashData(E) ((E)->data) /* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ #define sqliteHashCount(H) ((H)->count) #endif /* SQLITE_HASH_H */ /************** End of hash.h ************************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ /************** Include parse.h in the middle of sqliteInt.h *****************/ /************** Begin file parse.h *******************************************/ |
| ︙ | ︙ | |||
13472 13473 13474 13475 13476 13477 13478 | #define TK_DATABASE 38 #define TK_DESC 39 #define TK_DETACH 40 #define TK_EACH 41 #define TK_FAIL 42 #define TK_OR 43 #define TK_AND 44 | < | | | > | 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 13577 13578 13579 13580 | #define TK_DATABASE 38 #define TK_DESC 39 #define TK_DETACH 40 #define TK_EACH 41 #define TK_FAIL 42 #define TK_OR 43 #define TK_AND 44 #define TK_MATCH 45 #define TK_LIKE_KW 46 #define TK_BETWEEN 47 #define TK_IS 48 #define TK_IN 49 #define TK_ISNULL 50 #define TK_NOTNULL 51 #define TK_NE 52 #define TK_EQ 53 #define TK_GT 54 #define TK_LE 55 |
| ︙ | ︙ | |||
13716 13717 13718 13719 13720 13721 13722 | /* ** The default initial allocation for the pagecache when using separate ** pagecaches for each database connection. A positive number is the ** number of pages. A negative number N translations means that a buffer ** of -1024*N bytes is allocated and used for as many pages as it will hold. ** | | | 13807 13808 13809 13810 13811 13812 13813 13814 13815 13816 13817 13818 13819 13820 13821 | /* ** The default initial allocation for the pagecache when using separate ** pagecaches for each database connection. A positive number is the ** number of pages. A negative number N translations means that a buffer ** of -1024*N bytes is allocated and used for as many pages as it will hold. ** ** The default value of "20" was chosen to minimize the run-time of the ** speedtest1 test program with options: --shrink-memory --reprepare */ #ifndef SQLITE_DEFAULT_PCACHE_INITSZ # define SQLITE_DEFAULT_PCACHE_INITSZ 20 #endif /* |
| ︙ | ︙ | |||
14073 14074 14075 14076 14077 14078 14079 14080 | int (*xBusyHandler)(void *,int); /* The busy callback */ void *pBusyArg; /* First arg to busy callback */ int nBusy; /* Incremented with each busy call */ }; /* ** Name of table that holds the database schema. */ | > > > > > > > > > > > > > > | | | | | | 14164 14165 14166 14167 14168 14169 14170 14171 14172 14173 14174 14175 14176 14177 14178 14179 14180 14181 14182 14183 14184 14185 14186 14187 14188 14189 14190 14191 14192 14193 14194 14195 14196 14197 14198 14199 14200 14201 14202 14203 14204 14205 14206 14207 14208 |
int (*xBusyHandler)(void *,int); /* The busy callback */
void *pBusyArg; /* First arg to busy callback */
int nBusy; /* Incremented with each busy call */
};
/*
** Name of table that holds the database schema.
**
** The PREFERRED names are used whereever possible. But LEGACY is also
** used for backwards compatibility.
**
** 1. Queries can use either the PREFERRED or the LEGACY names
** 2. The sqlite3_set_authorizer() callback uses the LEGACY name
** 3. The PRAGMA table_list statement uses the PREFERRED name
**
** The LEGACY names are stored in the internal symbol hash table
** in support of (2). Names are translated using sqlite3PreferredTableName()
** for (3). The sqlite3FindTable() function takes care of translating
** names for (1).
**
** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema".
*/
#define LEGACY_SCHEMA_TABLE "sqlite_master"
#define LEGACY_TEMP_SCHEMA_TABLE "sqlite_temp_master"
#define PREFERRED_SCHEMA_TABLE "sqlite_schema"
#define PREFERRED_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
/*
** The root-page of the schema table.
*/
#define SCHEMA_ROOT 1
/*
** The name of the schema table. The name is different for TEMP.
*/
#define SCHEMA_TABLE(x) \
((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE)
/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
|
| ︙ | ︙ | |||
15157 15158 15159 15160 15161 15162 15163 | #define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */ #define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */ #define OP_ElseEq 58 /* jump, same as TK_ESCAPE */ #define OP_IfNotZero 59 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */ #define OP_DecrJumpZero 60 /* jump, synopsis: if (--r[P1])==0 goto P2 */ #define OP_IncrVacuum 61 /* jump */ #define OP_VNext 62 /* jump */ | > | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | < | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | > | | 15262 15263 15264 15265 15266 15267 15268 15269 15270 15271 15272 15273 15274 15275 15276 15277 15278 15279 15280 15281 15282 15283 15284 15285 15286 15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 15303 15304 15305 15306 15307 15308 15309 15310 15311 15312 15313 15314 15315 15316 15317 15318 15319 15320 15321 15322 15323 15324 15325 15326 15327 15328 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423 15424 15425 15426 15427 15428 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 |
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
#define OP_IfNotZero 59 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_DecrJumpZero 60 /* jump, synopsis: if (--r[P1])==0 goto P2 */
#define OP_IncrVacuum 61 /* jump */
#define OP_VNext 62 /* jump */
#define OP_Filter 63 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
#define OP_Init 64 /* jump, synopsis: Start at P2 */
#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */
#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */
#define OP_Return 67
#define OP_EndCoroutine 68
#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */
#define OP_Halt 70
#define OP_Integer 71 /* synopsis: r[P2]=P1 */
#define OP_Int64 72 /* synopsis: r[P2]=P4 */
#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */
#define OP_Null 74 /* synopsis: r[P2..P3]=NULL */
#define OP_SoftNull 75 /* synopsis: r[P1]=NULL */
#define OP_Blob 76 /* synopsis: r[P2]=P4 (len=P1) */
#define OP_Variable 77 /* synopsis: r[P2]=parameter(P1,P4) */
#define OP_Move 78 /* synopsis: r[P2@P3]=r[P1@P3] */
#define OP_Copy 79 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
#define OP_SCopy 80 /* synopsis: r[P2]=r[P1] */
#define OP_IntCopy 81 /* synopsis: r[P2]=r[P1] */
#define OP_FkCheck 82
#define OP_ResultRow 83 /* synopsis: output=r[P1@P2] */
#define OP_CollSeq 84
#define OP_AddImm 85 /* synopsis: r[P1]=r[P1]+P2 */
#define OP_RealAffinity 86
#define OP_Cast 87 /* synopsis: affinity(r[P1]) */
#define OP_Permutation 88
#define OP_Compare 89 /* synopsis: r[P1@P3] <-> r[P2@P3] */
#define OP_IsTrue 90 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
#define OP_ZeroOrNull 91 /* synopsis: r[P2] = 0 OR NULL */
#define OP_Offset 92 /* synopsis: r[P3] = sqlite_offset(P1) */
#define OP_Column 93 /* synopsis: r[P3]=PX */
#define OP_TypeCheck 94 /* synopsis: typecheck(r[P1@P2]) */
#define OP_Affinity 95 /* synopsis: affinity(r[P1@P2]) */
#define OP_MakeRecord 96 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
#define OP_Count 97 /* synopsis: r[P2]=count() */
#define OP_ReadCookie 98
#define OP_SetCookie 99
#define OP_ReopenIdx 100 /* synopsis: root=P2 iDb=P3 */
#define OP_OpenRead 101 /* synopsis: root=P2 iDb=P3 */
#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
#define OP_OpenWrite 112 /* synopsis: root=P2 iDb=P3 */
#define OP_BitNot 113 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
#define OP_OpenDup 114
#define OP_OpenAutoindex 115 /* synopsis: nColumn=P2 */
#define OP_String8 116 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_OpenEphemeral 117 /* synopsis: nColumn=P2 */
#define OP_SorterOpen 118
#define OP_SequenceTest 119 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
#define OP_OpenPseudo 120 /* synopsis: P3 columns in r[P2] */
#define OP_Close 121
#define OP_ColumnsUsed 122
#define OP_SeekScan 123 /* synopsis: Scan-ahead up to P1 rows */
#define OP_SeekHit 124 /* synopsis: set P2<=seekHit<=P3 */
#define OP_Sequence 125 /* synopsis: r[P2]=cursor[P1].ctr++ */
#define OP_NewRowid 126 /* synopsis: r[P2]=rowid */
#define OP_Insert 127 /* synopsis: intkey=r[P3] data=r[P2] */
#define OP_RowCell 128
#define OP_Delete 129
#define OP_ResetCount 130
#define OP_SorterCompare 131 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
#define OP_SorterData 132 /* synopsis: r[P2]=data */
#define OP_RowData 133 /* synopsis: r[P2]=data */
#define OP_Rowid 134 /* synopsis: r[P2]=rowid */
#define OP_NullRow 135
#define OP_SeekEnd 136
#define OP_IdxInsert 137 /* synopsis: key=r[P2] */
#define OP_SorterInsert 138 /* synopsis: key=r[P2] */
#define OP_IdxDelete 139 /* synopsis: key=r[P2@P3] */
#define OP_DeferredSeek 140 /* synopsis: Move P3 to P1.rowid if needed */
#define OP_IdxRowid 141 /* synopsis: r[P2]=rowid */
#define OP_FinishSeek 142
#define OP_Destroy 143
#define OP_Clear 144
#define OP_ResetSorter 145
#define OP_CreateBtree 146 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
#define OP_SqlExec 147
#define OP_ParseSchema 148
#define OP_LoadAnalysis 149
#define OP_DropTable 150
#define OP_DropIndex 151
#define OP_Real 152 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_DropTrigger 153
#define OP_IntegrityCk 154
#define OP_RowSetAdd 155 /* synopsis: rowset(P1)=r[P2] */
#define OP_Param 156
#define OP_FkCounter 157 /* synopsis: fkctr[P1]+=P2 */
#define OP_MemMax 158 /* synopsis: r[P1]=max(r[P1],r[P2]) */
#define OP_OffsetLimit 159 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
#define OP_AggInverse 160 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
#define OP_AggStep 161 /* synopsis: accum=r[P3] step(r[P2@P5]) */
#define OP_AggStep1 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */
#define OP_AggValue 163 /* synopsis: r[P3]=value N=P2 */
#define OP_AggFinal 164 /* synopsis: accum=r[P1] N=P2 */
#define OP_Expire 165
#define OP_CursorLock 166
#define OP_CursorUnlock 167
#define OP_TableLock 168 /* synopsis: iDb=P1 root=P2 write=P3 */
#define OP_VBegin 169
#define OP_VCreate 170
#define OP_VDestroy 171
#define OP_VOpen 172
#define OP_VColumn 173 /* synopsis: r[P3]=vcolumn(P2) */
#define OP_VRename 174
#define OP_Pagecount 175
#define OP_MaxPgcnt 176
#define OP_FilterAdd 177 /* synopsis: filter(P1) += key(P3@P4) */
#define OP_Trace 178
#define OP_CursorHint 179
#define OP_ReleaseReg 180 /* synopsis: release r[P1@P2] mask P3 */
#define OP_Noop 181
#define OP_Explain 182
#define OP_Abortable 183
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */
#define OPFLG_IN1 0x02 /* in1: P1 is an input */
#define OPFLG_IN2 0x04 /* in2: P2 is an input */
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x03, 0x01, 0x09,\
/* 24 */ 0x09, 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09,\
/* 32 */ 0x09, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
/* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\
/* 48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/* 72 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,\
/* 80 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02,\
/* 88 */ 0x00, 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00, 0x00,\
/* 96 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x26, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
/* 112 */ 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\
/* 136 */ 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00, 0x10,\
/* 144 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 152 */ 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
/* 176 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
}
/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
/*
** Additional non-public SQLITE_PREPARE_* flags
*/
|
| ︙ | ︙ | |||
16418 16419 16420 16421 16422 16423 16424 |
int nVdbeRead; /* Number of active VDBEs that read or write */
int nVdbeWrite; /* Number of active VDBEs that read and write */
int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
union {
| | | | > > > | 16526 16527 16528 16529 16530 16531 16532 16533 16534 16535 16536 16537 16538 16539 16540 16541 16542 16543 16544 16545 16546 16547 16548 16549 16550 16551 16552 16553 16554 16555 16556 |
int nVdbeRead; /* Number of active VDBEs that read or write */
int nVdbeWrite; /* Number of active VDBEs that read and write */
int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
union {
void (*xLegacy)(void*,const char*); /* mTrace==SQLITE_TRACE_LEGACY */
int (*xV2)(u32,void*,void*,void*); /* All other mTrace values */
} trace;
void *pTraceArg; /* Argument to the trace function */
#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
#endif
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
void *pRollbackArg; /* Argument to xRollbackCallback() */
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
void *pAutovacPagesArg; /* Client argument to autovac_pages */
void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
Parse *pParse; /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */
void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
);
PreUpdate *pPreUpdate; /* Context for active pre-update callback */
|
| ︙ | ︙ | |||
16561 16562 16563 16564 16565 16566 16567 16568 16569 16570 16571 16572 16573 16574 |
#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
| > | 16672 16673 16674 16675 16676 16677 16678 16679 16680 16681 16682 16683 16684 16685 16686 |
#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
|
| ︙ | ︙ | |||
16609 16610 16611 16612 16613 16614 16615 16616 16617 16618 16619 16620 16621 16622 | #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) | > > | 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 | #define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_SkipScan 0x00004000 /* Skip-scans */ #define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */ #define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */ #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ #define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
| ︙ | ︙ | |||
16657 16658 16659 16660 16661 16662 16663 |
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
void (*xValue)(sqlite3_context*); /* Current agg value */
void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */
const char *zName; /* SQL name of the function. */
union {
FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
| | | 16771 16772 16773 16774 16775 16776 16777 16778 16779 16780 16781 16782 16783 16784 16785 |
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
void (*xValue)(sqlite3_context*); /* Current agg value */
void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */
const char *zName; /* SQL name of the function. */
union {
FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
} u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */
};
/*
** This structure encapsulates a user-function destructor callback (as
** configured using create_function_v2()) and a reference counter. When
** create_function_v2() is called to create a function with a destructor,
** a single object of this type is allocated. FuncDestructor.nRef is set to
|
| ︙ | ︙ | |||
16718 16719 16720 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 | #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ #define INLINEFUNC_coalesce 0 #define INLINEFUNC_implies_nonnull_row 1 #define INLINEFUNC_expr_implies_expr 2 #define INLINEFUNC_expr_compare 3 | > | 16832 16833 16834 16835 16836 16837 16838 16839 16840 16841 16842 16843 16844 16845 16846 | #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ #define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */ #define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */ #define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */ #define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */ /* Identifier numbers for each in-line function */ #define INLINEFUNC_coalesce 0 #define INLINEFUNC_implies_nonnull_row 1 #define INLINEFUNC_expr_implies_expr 2 #define INLINEFUNC_expr_compare 3 |
| ︙ | ︙ | |||
16796 16797 16798 16799 16800 16801 16802 | ** that accepts nArg arguments and is implemented by a call to C ** function likeFunc. Argument pArg is cast to a (void *) and made ** available as the function user-data (sqlite3_user_data()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ | > | | | | > | > | | > | > | > | | | > | | 16911 16912 16913 16914 16915 16916 16917 16918 16919 16920 16921 16922 16923 16924 16925 16926 16927 16928 16929 16930 16931 16932 16933 16934 16935 16936 16937 16938 16939 16940 16941 16942 16943 16944 16945 16946 16947 16948 16949 16950 16951 16952 16953 16954 16955 16956 16957 16958 16959 16960 16961 16962 16963 16964 16965 16966 16967 16968 16969 |
** that accepts nArg arguments and is implemented by a call to C
** function likeFunc. Argument pArg is cast to a (void *) and made
** available as the function user-data (sqlite3_user_data()). The
** FuncDef.flags variable is set to the value passed as the flags
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
(void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, 0, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
/*
** All current savepoints are stored in a linked list starting at
** sqlite3.pSavepoint. The first element in the list is the most recently
** opened savepoint. Savepoints are added to the list by the vdbe
|
| ︙ | ︙ | |||
17556 17557 17558 17559 17560 17561 17562 | ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** ** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, | | | | | 17678 17679 17680 17681 17682 17683 17684 17685 17686 17687 17688 17689 17690 17691 17692 17693 17694 17695 | ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused ** to represent the greater-than-or-equal-to operator in the expression ** tree. ** ** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, ** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If ** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the ** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), ** then Expr.u.zToken contains the name of the function. ** ** Expr.pRight and Expr.pLeft are the left and right subexpressions of a ** binary operator. Either or both may be NULL. ** ** Expr.x.pList is a list of arguments if the expression is an SQL function, ** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)". ** Expr.x.pSelect is used if the expression is a sub-select or an expression of |
| ︙ | ︙ | |||
17599 17600 17601 17602 17603 17604 17605 | ** ** ALLOCATION NOTES: ** ** Expr objects can use a lot of memory space in database schema. To ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, | | | 17721 17722 17723 17724 17725 17726 17727 17728 17729 17730 17731 17732 17733 17734 17735 | ** ** ALLOCATION NOTES: ** ** Expr objects can use a lot of memory space in database schema. To ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, ** together with Expr.u.zToken strings. ** ** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all ** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees ** are contained within the same memory allocation. Note, however, that ** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately ** allocated, regardless of whether or not EP_Reduced is set. |
| ︙ | ︙ | |||
17668 17669 17670 17671 17672 17673 17674 |
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
} sub;
} y;
};
| < | | 17790 17791 17792 17793 17794 17795 17796 17797 17798 17799 17800 17801 17802 17803 17804 |
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
} sub;
} y;
};
/* The following are the meanings of bits in the Expr.flags field.
** Value restrictions:
**
** EP_Agg == NC_HasAgg == SF_HasAgg
** EP_Win == NC_HasWin
*/
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
|
| ︙ | ︙ | |||
17708 17709 17710 17711 17712 17713 17714 |
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
/* 0x80000000 // Available */
| < | < | > > > > > > > > > > | 17829 17830 17831 17832 17833 17834 17835 17836 17837 17838 17839 17840 17841 17842 17843 17844 17845 17846 17847 17848 17849 17850 17851 17852 17853 17854 17855 17856 17857 17858 17859 17860 17861 17862 17863 17864 17865 17866 17867 |
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
/* 0x80000000 // Available */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
*/
#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
#define ExprSetProperty(E,P) (E)->flags|=(P)
#define ExprClearProperty(E,P) (E)->flags&=~(P)
#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
/* Macros used to ensure that the correct members of unions are accessed
** in Expr.
*/
#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
#define ExprUseYWin(E) (((E)->flags&EP_WinFunc)!=0)
#define ExprUseYSub(E) (((E)->flags&EP_Subrtn)!=0)
/* Flags for use with Expr.vvaFlags
*/
#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Immutable 0x02 /* Do not change this Expr node */
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
|
| ︙ | ︙ | |||
17807 17808 17809 17810 17811 17812 17813 |
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
unsigned eEName :2; /* Meaning of zEName */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
union {
| | | > | 17936 17937 17938 17939 17940 17941 17942 17943 17944 17945 17946 17947 17948 17949 17950 17951 17952 17953 17954 17955 |
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
unsigned eEName :2; /* Meaning of zEName */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
union {
struct { /* Used by any ExprList other than Parse.pConsExpr */
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} x;
int iConstExprReg; /* Register in which Expr value is cached. Used only
** by Parse.pConstExpr */
} u;
} a[1]; /* One slot for each expression in the list */
};
/*
** Allowed values for Expr.a.eEName
*/
|
| ︙ | ︙ | |||
17849 17850 17851 17852 17853 17854 17855 17856 17857 17858 17859 17860 17861 17862 |
} *a;
int nId; /* Number of identifiers on the list */
};
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
*/
struct SrcItem {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
| > > > > > > > | 17979 17980 17981 17982 17983 17984 17985 17986 17987 17988 17989 17990 17991 17992 17993 17994 17995 17996 17997 17998 17999 |
} *a;
int nId; /* Number of identifiers on the list */
};
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
** Union member validity:
**
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
** u2.pCteUse fg.isCte && !fg.isIndexedBy
*/
struct SrcItem {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
Table *pTab; /* An SQL table corresponding to zName */
|
| ︙ | ︙ | |||
18380 18381 18382 18383 18384 18385 18386 | #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ | < | 18517 18518 18519 18520 18521 18522 18523 18524 18525 18526 18527 18528 18529 18530 |
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
union {
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
Returning *pReturning; /* The RETURNING clause */
} u1;
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
|
| ︙ | ︙ | |||
18443 18444 18445 18446 18447 18448 18449 18450 18451 18452 18453 18454 18455 18456 | With *pWith; /* Current WITH clause, or NULL */ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif }; #define PARSE_MODE_NORMAL 0 #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME 2 #define PARSE_MODE_UNMAP 3 /* ** Sizes and pointers of various parts of the Parse object. | > > | 18579 18580 18581 18582 18583 18584 18585 18586 18587 18588 18589 18590 18591 18592 18593 18594 | With *pWith; /* Current WITH clause, or NULL */ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif }; /* Allowed values for Parse.eParseMode */ #define PARSE_MODE_NORMAL 0 #define PARSE_MODE_DECLARE_VTAB 1 #define PARSE_MODE_RENAME 2 #define PARSE_MODE_UNMAP 3 /* ** Sizes and pointers of various parts of the Parse object. |
| ︙ | ︙ | |||
18664 18665 18666 18667 18668 18669 18670 18671 18672 18673 18674 18675 18676 18677 18678 18679 | u32 nInitRow; /* Number of rows processed */ Pgno mxPage; /* Maximum page number. 0 for no limit. */ } InitData; /* ** Allowed values for mInitFlags */ #define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ #define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning ** parameters are for temporary use during development, to help find ** optimial values for parameters in the query planner. The should not ** be used on trunk check-ins. They are a temporary mechanism available ** for transient development builds only. | > > | 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 18814 18815 18816 18817 18818 18819 | u32 nInitRow; /* Number of rows processed */ Pgno mxPage; /* Maximum page number. 0 for no limit. */ } InitData; /* ** Allowed values for mInitFlags */ #define INITFLAG_AlterMask 0x0003 /* Types of ALTER */ #define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */ #define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */ #define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */ /* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled ** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning ** parameters are for temporary use during development, to help find ** optimial values for parameters in the query planner. The should not ** be used on trunk check-ins. They are a temporary mechanism available ** for transient development builds only. |
| ︙ | ︙ | |||
18786 18787 18788 18789 18790 18791 18792 |
int walkerDepth; /* Number of subqueries */
u16 eCode; /* A small processing code */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
int iCur; /* A cursor number */
SrcList *pSrcList; /* FROM clause */
| < > | 18926 18927 18928 18929 18930 18931 18932 18933 18934 18935 18936 18937 18938 18939 18940 18941 |
int walkerDepth; /* Number of subqueries */
u16 eCode; /* A small processing code */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
int iCur; /* A cursor number */
SrcList *pSrcList; /* FROM clause */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
ExprList *pGroupBy; /* GROUP BY clause */
Select *pSelect; /* HAVING to WHERE clause ctx */
struct WindowRewrite *pRewrite; /* Window rewrite context */
struct WhereConst *pConst; /* WHERE clause constants */
|
| ︙ | ︙ | |||
19385 19386 19387 19388 19389 19390 19391 19392 19393 19394 19395 19396 19397 19398 |
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
Upsert*);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
| > | 19525 19526 19527 19528 19529 19530 19531 19532 19533 19534 19535 19536 19537 19538 19539 |
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*);
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
Upsert*);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
|
| ︙ | ︙ | |||
19428 19429 19430 19431 19432 19433 19434 19435 19436 19437 19438 19439 19440 19441 19442 19443 19444 19445 19446 19447 19448 19449 19450 | SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, const Token*); SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int); SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int); SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int); SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); | > | | 19569 19570 19571 19572 19573 19574 19575 19576 19577 19578 19579 19580 19581 19582 19583 19584 19585 19586 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 | SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int); SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int); SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*); #define LOCATE_VIEW 0x01 #define LOCATE_NOERR 0x02 SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*); SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char*); SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *); SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*); SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*); SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, const Token*); SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int); SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int); SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int); SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*); SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); #ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); #endif SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); |
| ︙ | ︙ | |||
19594 19595 19596 19597 19598 19599 19600 | #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); #endif SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); | < < < < < < | 19736 19737 19738 19739 19740 19741 19742 19743 19744 19745 19746 19747 19748 19749 19750 19751 | #ifndef SQLITE_OMIT_UTF16 SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar); #endif SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); /* ** Routines to read and write variable-length integers. These used to ** be defined locally, but now we use the varint routines in the util.c |
| ︙ | ︙ | |||
19886 19887 19888 19889 19890 19891 19892 19893 19894 19895 19896 19897 19898 19899 19900 19901 19902 | ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db); #ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName); SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); #else # define sqlite3ShadowTableName(A,B) 0 # define sqlite3IsShadowTableOf(A,B,C) 0 #endif SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); | > > | 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 | ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db); #ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName); SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*); #else # define sqlite3ShadowTableName(A,B) 0 # define sqlite3IsShadowTableOf(A,B,C) 0 # define sqlite3MarkAllShadowTablesOf(A,B) #endif SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*); SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*); SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); |
| ︙ | ︙ | |||
19931 19932 19933 19934 19935 19936 19937 | SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) # define sqlite3CteDelete(D,C) # define sqlite3CteWithAdd(P,W,C) ((void*)0) # define sqlite3WithDelete(x,y) | | | 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 20081 20082 20083 | SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) # define sqlite3CteDelete(D,C) # define sqlite3CteWithAdd(P,W,C) ((void*)0) # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) ((void*)0) #endif #ifndef SQLITE_OMIT_UPSERT SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*); SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*); SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*); SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*); SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int); |
| ︙ | ︙ | |||
20099 20100 20101 20102 20103 20104 20105 | ** this constraint. ** ** All of this is no-op for a production build. It only comes into ** play when the SQLITE_MEMDEBUG compile-time option is used. */ #ifdef SQLITE_MEMDEBUG SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8); | | | | 20237 20238 20239 20240 20241 20242 20243 20244 20245 20246 20247 20248 20249 20250 20251 20252 | ** this constraint. ** ** All of this is no-op for a production build. It only comes into ** play when the SQLITE_MEMDEBUG compile-time option is used. */ #ifdef SQLITE_MEMDEBUG SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8); SQLITE_PRIVATE int sqlite3MemdebugHasType(const void*,u8); SQLITE_PRIVATE int sqlite3MemdebugNoType(const void*,u8); #else # define sqlite3MemdebugSetType(X,Y) /* no-op */ # define sqlite3MemdebugHasType(X,Y) 1 # define sqlite3MemdebugNoType(X,Y) 1 #endif #define MEMTYPE_HEAP 0x01 /* General heap allocations */ #define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */ |
| ︙ | ︙ | |||
21423 21424 21425 21426 21427 21428 21429 21430 21431 21432 21433 21434 21435 21436 | /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. */ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; #ifdef VDBE_PROFILE /* ** The following performance counter can be used in place of ** sqlite3Hwtime() for profiling. This is a no-op on standard builds. */ SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; #endif | > > > > > > > > > > > > | 21561 21562 21563 21564 21565 21566 21567 21568 21569 21570 21571 21572 21573 21574 21575 21576 21577 21578 21579 21580 21581 21582 21583 21584 21585 21586 | /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. */ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG) /* ** Counter used for coverage testing. Does not come into play for ** release builds. ** ** Access to this global variable is not mutex protected. This might ** result in TSAN warnings. But as the variable does not exist in ** release builds, that should not be a concern. */ SQLITE_PRIVATE unsigned int sqlite3CoverageCounter; #endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */ #ifdef VDBE_PROFILE /* ** The following performance counter can be used in place of ** sqlite3Hwtime() for profiling. This is a no-op on standard builds. */ SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; #endif |
| ︙ | ︙ | |||
21967 21968 21969 21970 21971 21972 21973 | bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ | | | 22117 22118 22119 22120 22121 22122 22123 22124 22125 22126 22127 22128 22129 22130 22131 | bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ #ifdef SQLITE_ENABLE_NORMALIZE char *zNormSql; /* Normalization of the associated SQL statement */ DblquoteStr *pDblStr; /* List of double-quoted string literals */ #endif void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ |
| ︙ | ︙ | |||
22063 22064 22065 22066 22067 22068 22069 22070 22071 22072 22073 22074 22075 22076 22077 | # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); | > > > > | | 22213 22214 22215 22216 22217 22218 22219 22220 22221 22222 22223 22224 22225 22226 22227 22228 22229 22230 22231 22232 22233 22234 22235 22236 22237 22238 22239 | # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*); #ifndef SQLITE_OMIT_INCRBLOB SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int); #else SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int); #endif #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*); #endif SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8); |
| ︙ | ︙ | |||
23069 23070 23071 23072 23073 23074 23075 23076 23077 23078 23079 23080 23081 23082 23083 | #endif sqlite3_mutex_enter(mutex); pX = localtime(t); #ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; sqlite3_mutex_leave(mutex); rc = pX==0; #else #ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; | > > | 23223 23224 23225 23226 23227 23228 23229 23230 23231 23232 23233 23234 23235 23236 23237 23238 23239 | #endif sqlite3_mutex_enter(mutex); pX = localtime(t); #ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; #endif if( pX ) *pTm = *pX; #if SQLITE_THREADSAFE>0 sqlite3_mutex_leave(mutex); #endif rc = pX==0; #else #ifndef SQLITE_UNTESTABLE if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; |
| ︙ | ︙ | |||
23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 23221 |
const char *z, /* The text of the modifier */
int n, /* Length of zMod in bytes */
DateTime *p /* The date/time value to be modified */
){
int rc = 1;
double r;
switch(sqlite3UpperToLower[(u8)z[0]] ){
#ifndef SQLITE_OMIT_LOCALTIME
case 'l': {
/* localtime
**
** Assuming the current time value is UTC (a.k.a. GMT), shift it to
** show local time.
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 23364 23365 23366 23367 23368 23369 23370 23371 23372 23373 23374 23375 23376 23377 23378 23379 23380 23381 23382 23383 23384 23385 23386 23387 23388 23389 23390 23391 23392 23393 23394 23395 23396 23397 23398 23399 23400 23401 23402 23403 23404 23405 23406 23407 23408 23409 23410 23411 23412 23413 23414 23415 23416 |
const char *z, /* The text of the modifier */
int n, /* Length of zMod in bytes */
DateTime *p /* The date/time value to be modified */
){
int rc = 1;
double r;
switch(sqlite3UpperToLower[(u8)z[0]] ){
case 'a': {
/*
** auto
**
** If rawS is available, then interpret as a julian day number, or
** a unix timestamp, depending on its magnitude.
*/
if( sqlite3_stricmp(z, "auto")==0 ){
if( !p->rawS || p->validJD ){
rc = 0;
p->rawS = 0;
}else if( p->s>=-210866760000 && p->s<=253402300799 ){
r = p->s*1000.0 + 210866760000000.0;
clearYMD_HMS_TZ(p);
p->iJD = (sqlite3_int64)(r + 0.5);
p->validJD = 1;
p->rawS = 0;
rc = 0;
}
}
break;
}
case 'j': {
/*
** julianday
**
** Always interpret the prior number as a julian-day value. If this
** is not the first modifier, or if the prior argument is not a numeric
** value in the allowed range of julian day numbers understood by
** SQLite (0..5373484.5) then the result will be NULL.
*/
if( sqlite3_stricmp(z, "julianday")==0 ){
if( p->validJD && p->rawS ){
rc = 0;
p->rawS = 0;
}
}
break;
}
#ifndef SQLITE_OMIT_LOCALTIME
case 'l': {
/* localtime
**
** Assuming the current time value is UTC (a.k.a. GMT), shift it to
** show local time.
*/
|
| ︙ | ︙ | |||
23471 23472 23473 23474 23475 23476 23477 23478 23479 23480 23481 23482 23483 23484 |
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
computeJD(&x);
sqlite3_result_double(context, x.iJD/86400000.0);
}
}
/*
** datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(
| > > > > > > > > > > > > > > > > > > | 23666 23667 23668 23669 23670 23671 23672 23673 23674 23675 23676 23677 23678 23679 23680 23681 23682 23683 23684 23685 23686 23687 23688 23689 23690 23691 23692 23693 23694 23695 23696 23697 |
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
computeJD(&x);
sqlite3_result_double(context, x.iJD/86400000.0);
}
}
/*
** unixepoch( TIMESTRING, MOD, MOD, ...)
**
** Return the number of seconds (including fractional seconds) since
** the unix epoch of 1970-01-01 00:00:00 GMT.
*/
static void unixepochFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
computeJD(&x);
sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
}
}
/*
** datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(
|
| ︙ | ︙ | |||
23571 23572 23573 23574 23575 23576 23577 |
db = sqlite3_context_db_handle(context);
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
if( zFmt[i]!='%' ) continue;
| | | 23784 23785 23786 23787 23788 23789 23790 23791 23792 23793 23794 23795 23796 23797 23798 |
db = sqlite3_context_db_handle(context);
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
if( zFmt[i]!='%' ) continue;
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
i++;
j = i + 1;
switch( zFmt[i] ){
case 'd': {
sqlite3_str_appendf(&sRes, "%02d", x.D);
break;
}
|
| ︙ | ︙ | |||
23647 23648 23649 23650 23651 23652 23653 |
}
default: {
sqlite3_str_reset(&sRes);
return;
}
}
}
| | | 23860 23861 23862 23863 23864 23865 23866 23867 23868 23869 23870 23871 23872 23873 23874 |
}
default: {
sqlite3_str_reset(&sRes);
return;
}
}
}
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
sqlite3ResultStrAccum(context, &sRes);
}
/*
** current_time()
**
** This function returns the same value as time('now').
|
| ︙ | ︙ | |||
23748 23749 23750 23751 23752 23753 23754 23755 23756 23757 23758 23759 23760 23761 |
** functions. This should be the only routine in this file with
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
PURE_DATE(date, -1, 0, 0, dateFunc ),
PURE_DATE(time, -1, 0, 0, timeFunc ),
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
| > | 23961 23962 23963 23964 23965 23966 23967 23968 23969 23970 23971 23972 23973 23974 23975 |
** functions. This should be the only routine in this file with
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
PURE_DATE(date, -1, 0, 0, dateFunc ),
PURE_DATE(time, -1, 0, 0, timeFunc ),
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
| ︙ | ︙ | |||
24084 24085 24086 24087 24088 24089 24090 24091 24092 24093 24094 24095 24096 24097 24098 24099 24100 24101 24102 24103 |
int rc;
sqlite3_file *pFile;
pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
if( pFile ){
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlite3_free(pFile);
}else{
*ppFile = pFile;
}
}else{
rc = SQLITE_NOMEM_BKPT;
}
return rc;
}
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){
assert( pFile );
sqlite3OsClose(pFile);
sqlite3_free(pFile);
}
| > > > | 24298 24299 24300 24301 24302 24303 24304 24305 24306 24307 24308 24309 24310 24311 24312 24313 24314 24315 24316 24317 24318 24319 24320 |
int rc;
sqlite3_file *pFile;
pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
if( pFile ){
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlite3_free(pFile);
*ppFile = 0;
}else{
*ppFile = pFile;
}
}else{
*ppFile = 0;
rc = SQLITE_NOMEM_BKPT;
}
assert( *ppFile!=0 || rc!=SQLITE_OK );
return rc;
}
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){
assert( pFile );
sqlite3OsClose(pFile);
sqlite3_free(pFile);
}
|
| ︙ | ︙ | |||
24807 24808 24809 24810 24811 24812 24813 | /* ** Given an allocation, find the MemBlockHdr for that allocation. ** ** This routine checks the guards at either end of the allocation and ** if they are incorrect it asserts. */ | | | 25024 25025 25026 25027 25028 25029 25030 25031 25032 25033 25034 25035 25036 25037 25038 |
/*
** Given an allocation, find the MemBlockHdr for that allocation.
**
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
struct MemBlockHdr *p;
int *pInt;
u8 *pU8;
int nReserve;
p = (struct MemBlockHdr*)pAllocation;
p--;
|
| ︙ | ︙ | |||
25054 25055 25056 25057 25058 25059 25060 | ** allocation p. Also return true if p==NULL. ** ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); */ | | | 25271 25272 25273 25274 25275 25276 25277 25278 25279 25280 25281 25282 25283 25284 25285 |
** allocation p. Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
SQLITE_PRIVATE int sqlite3MemdebugHasType(const void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
if( (pHdr->eType&eType)==0 ){
rc = 0;
|
| ︙ | ︙ | |||
25076 25077 25078 25079 25080 25081 25082 | ** allocation p. Also return true if p==NULL. ** ** This routine is designed for use within an assert() statement, to ** verify the type of an allocation. For example: ** ** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); */ | | | 25293 25294 25295 25296 25297 25298 25299 25300 25301 25302 25303 25304 25305 25306 25307 |
** allocation p. Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
SQLITE_PRIVATE int sqlite3MemdebugNoType(const void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
if( (pHdr->eType&eType)!=0 ){
rc = 0;
|
| ︙ | ︙ | |||
30541 30542 30543 30544 30545 30546 30547 30548 30549 30550 30551 30552 30553 30554 30555 30556 30557 30558 30559 30560 30561 30562 30563 30564 30565 30566 30567 30568 30569 30570 30571 30572 30573 30574 30575 30576 30577 30578 30579 30580 30581 30582 30583 30584 30585 30586 30587 30588 30589 30590 30591 30592 30593 30594 30595 30596 30597 30598 30599 30600 30601 30602 30603 30604 30605 30606 30607 30608 30609 30610 30611 30612 |
sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
}else{
zOp2[0] = 0;
}
sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
pExpr->iColumn, zFlgs, zOp2);
}else{
sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
pExpr->iTable, pExpr->iColumn,
pExpr->y.pTab, zFlgs);
}
if( ExprHasProperty(pExpr, EP_FixedCol) ){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
case TK_TRUEFALSE: {
sqlite3TreeViewLine(pView,"%s%s",
sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
| > > > > > > > | 30758 30759 30760 30761 30762 30763 30764 30765 30766 30767 30768 30769 30770 30771 30772 30773 30774 30775 30776 30777 30778 30779 30780 30781 30782 30783 30784 30785 30786 30787 30788 30789 30790 30791 30792 30793 30794 30795 30796 30797 30798 30799 30800 30801 30802 30803 30804 30805 30806 30807 30808 30809 30810 30811 30812 30813 30814 30815 30816 30817 30818 30819 30820 30821 30822 30823 30824 30825 30826 30827 30828 30829 30830 30831 30832 30833 30834 30835 30836 |
sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
}else{
zOp2[0] = 0;
}
sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
pExpr->iColumn, zFlgs, zOp2);
}else{
assert( ExprUseYTab(pExpr) );
sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
pExpr->iTable, pExpr->iColumn,
pExpr->y.pTab, zFlgs);
}
if( ExprHasProperty(pExpr, EP_FixedCol) ){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
case TK_TRUEFALSE: {
sqlite3TreeViewLine(pView,"%s%s",
sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_ID: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
|
| ︙ | ︙ | |||
30648 30649 30650 30651 30652 30653 30654 30655 30656 30657 30658 30659 30660 30661 30662 30663 30664 30665 30666 30667 30668 30669 30670 30671 30672 30673 30674 30675 30676 30677 30678 30679 30680 30681 30682 30683 30684 30685 30686 30687 30688 30689 30690 30691 30692 30693 30694 |
assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
zUniOp = azOp[x];
break;
}
case TK_SPAN: {
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_COLLATE: {
/* COLLATE operators without the EP_Collate flag are intended to
** emulate collation associated with a table column. These show
** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
** operators that appear in the original SQL always have the
** EP_Collate bit set and appear in treeview output as just "COLLATE" */
sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
!ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
pExpr->u.zToken, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
Window *pWin;
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
pWin = 0;
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
pExpr->op2, pExpr->u.zToken, zFlgs,
pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
pExpr->iAgg, pExpr->pAggInfo);
}else if( pExpr->op2!=0 ){
const char *zOp2;
| > > > > | 30872 30873 30874 30875 30876 30877 30878 30879 30880 30881 30882 30883 30884 30885 30886 30887 30888 30889 30890 30891 30892 30893 30894 30895 30896 30897 30898 30899 30900 30901 30902 30903 30904 30905 30906 30907 30908 30909 30910 30911 30912 30913 30914 30915 30916 30917 30918 30919 30920 30921 30922 |
assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
zUniOp = azOp[x];
break;
}
case TK_SPAN: {
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_COLLATE: {
/* COLLATE operators without the EP_Collate flag are intended to
** emulate collation associated with a table column. These show
** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
** operators that appear in the original SQL always have the
** EP_Collate bit set and appear in treeview output as just "COLLATE" */
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
!ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
pExpr->u.zToken, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
Window *pWin;
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
pWin = 0;
}else{
assert( ExprUseXList(pExpr) );
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
#endif
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
pExpr->op2, pExpr->u.zToken, zFlgs,
pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
pExpr->iAgg, pExpr->pAggInfo);
}else if( pExpr->op2!=0 ){
const char *zOp2;
|
| ︙ | ︙ | |||
30712 30713 30714 30715 30716 30717 30718 30719 30720 30721 30722 30723 30724 30725 30726 30727 30728 30729 30730 |
sqlite3TreeViewWindow(pView, pWin, 0);
}
#endif
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
| > > | > | > > | | | 30940 30941 30942 30943 30944 30945 30946 30947 30948 30949 30950 30951 30952 30953 30954 30955 30956 30957 30958 30959 30960 30961 30962 30963 30964 30965 30966 30967 30968 30969 30970 30971 30972 30973 30974 30975 30976 30977 30978 30979 30980 30981 30982 30983 30984 30985 30986 30987 30988 30989 30990 30991 30992 30993 30994 |
sqlite3TreeViewWindow(pView, pWin, 0);
}
#endif
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
assert( ExprUseXSelect(pExpr) );
sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
assert( ExprUseXSelect(pExpr) );
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprUseXSelect(pExpr) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
const Expr *pX, *pY, *pZ;
pX = pExpr->pLeft;
assert( ExprUseXList(pExpr) );
assert( pExpr->x.pList->nExpr==2 );
pY = pExpr->x.pList->a[0].pExpr;
pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
|
| ︙ | ︙ | |||
30769 30770 30771 30772 30773 30774 30775 30776 30777 30778 30779 30780 30781 30782 30783 30784 30785 30786 30787 30788 30789 30790 30791 30792 30793 30794 30795 30796 30797 30798 30799 30800 30801 30802 30803 30804 30805 30806 30807 30808 30809 30810 30811 30812 30813 30814 |
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affExpr ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
case TK_MATCH: {
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
pExpr->iTable, pExpr->iColumn, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
break;
}
case TK_VECTOR: {
char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
pExpr->iColumn, pExpr->iTable-1,
pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
case TK_IF_NULL_ROW: {
sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
| > > > > | 31002 31003 31004 31005 31006 31007 31008 31009 31010 31011 31012 31013 31014 31015 31016 31017 31018 31019 31020 31021 31022 31023 31024 31025 31026 31027 31028 31029 31030 31031 31032 31033 31034 31035 31036 31037 31038 31039 31040 31041 31042 31043 31044 31045 31046 31047 31048 31049 31050 31051 |
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
assert( ExprUseXList(pExpr) );
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affExpr ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
case TK_MATCH: {
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
pExpr->iTable, pExpr->iColumn, zFlgs);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
break;
}
case TK_VECTOR: {
char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
assert( ExprUseXList(pExpr) );
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
pExpr->iColumn, pExpr->iTable-1,
pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
assert( ExprUseXSelect(pExpr->pLeft) );
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
case TK_IF_NULL_ROW: {
sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
|
| ︙ | ︙ | |||
31877 31878 31879 31880 31881 31882 31883 | */ /* #include "sqliteInt.h" */ /* #include <stdarg.h> */ #ifndef SQLITE_OMIT_FLOATING_POINT #include <math.h> #endif | < < < < < < < < < < | 32114 32115 32116 32117 32118 32119 32120 32121 32122 32123 32124 32125 32126 32127 | */ /* #include "sqliteInt.h" */ /* #include <stdarg.h> */ #ifndef SQLITE_OMIT_FLOATING_POINT #include <math.h> #endif /* ** Calls to sqlite3FaultSim() are used to simulate a failure during testing, ** or to bypass normal error detection during testing in order to let ** execute proceed futher downstream. ** ** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The ** sqlite3FaultSim() function only returns non-zero during testing. |
| ︙ | ︙ | |||
32133 32134 32135 32136 32137 32138 32139 32140 32141 32142 32143 32144 32145 32146 |
}else{
z[j++] = z[i];
}
}
z[j] = 0;
}
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
assert( sqlite3Isquote(p->u.zToken[0]) );
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
sqlite3Dequote(p->u.zToken);
}
/*
** If the input token p is quoted, try to adjust the token to remove
| > | 32360 32361 32362 32363 32364 32365 32366 32367 32368 32369 32370 32371 32372 32373 32374 |
}else{
z[j++] = z[i];
}
}
z[j] = 0;
}
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
assert( !ExprHasProperty(p, EP_IntValue) );
assert( sqlite3Isquote(p->u.zToken[0]) );
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
sqlite3Dequote(p->u.zToken);
}
/*
** If the input token p is quoted, try to adjust the token to remove
|
| ︙ | ︙ | |||
33451 33452 33453 33454 33455 33456 33457 |
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; }
#endif
}
return a[x&7] + y - 10;
}
| < < < < < < < < < < < < < < < < | 33679 33680 33681 33682 33683 33684 33685 33686 33687 33688 33689 33690 33691 33692 33693 33694 33695 33696 33697 33698 33699 33700 33701 33702 33703 33704 33705 33706 33707 33708 33709 33710 33711 33712 33713 33714 33715 33716 33717 33718 33719 |
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; }
#endif
}
return a[x&7] + y - 10;
}
/*
** Convert a double into a LogEst
** In other words, compute an approximation for 10*log2(x).
*/
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
u64 a;
LogEst e;
assert( sizeof(x)==8 && sizeof(a)==8 );
if( x<=1 ) return 0;
if( x<=2000000000 ) return sqlite3LogEst((u64)x);
memcpy(&a, &x, 8);
e = (a>>52) - 1022;
return e*10;
}
/*
** Convert a LogEst into an integer.
*/
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
u64 n;
n = x%10;
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
if( x>60 ) return (u64)LARGEST_INT64;
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
/*
** Add a new name/number pair to a VList. This might require that the
** VList object be reallocated, so return the new VList. If an OOM
** error occurs, the original VList returned and the
** db->mallocFailed flag is set.
**
|
| ︙ | ︙ | |||
33947 33948 33949 33950 33951 33952 33953 |
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 58 */ "ElseEq" OpHelp(""),
/* 59 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 60 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 61 */ "IncrVacuum" OpHelp(""),
/* 62 */ "VNext" OpHelp(""),
| > | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | < | > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | 34159 34160 34161 34162 34163 34164 34165 34166 34167 34168 34169 34170 34171 34172 34173 34174 34175 34176 34177 34178 34179 34180 34181 34182 34183 34184 34185 34186 34187 34188 34189 34190 34191 34192 34193 34194 34195 34196 34197 34198 34199 34200 34201 34202 34203 34204 34205 34206 34207 34208 34209 34210 34211 34212 34213 34214 34215 34216 34217 34218 34219 34220 34221 34222 34223 34224 34225 34226 34227 34228 34229 34230 34231 34232 34233 34234 34235 34236 34237 34238 34239 34240 34241 34242 34243 34244 34245 34246 34247 34248 34249 34250 34251 34252 34253 34254 34255 34256 34257 34258 34259 34260 34261 34262 34263 34264 34265 34266 34267 34268 34269 34270 34271 34272 34273 34274 34275 34276 34277 34278 34279 34280 34281 34282 34283 34284 34285 34286 34287 34288 34289 34290 34291 34292 34293 |
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 58 */ "ElseEq" OpHelp(""),
/* 59 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 60 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 61 */ "IncrVacuum" OpHelp(""),
/* 62 */ "VNext" OpHelp(""),
/* 63 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
/* 64 */ "Init" OpHelp("Start at P2"),
/* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
/* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
/* 67 */ "Return" OpHelp(""),
/* 68 */ "EndCoroutine" OpHelp(""),
/* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
/* 70 */ "Halt" OpHelp(""),
/* 71 */ "Integer" OpHelp("r[P2]=P1"),
/* 72 */ "Int64" OpHelp("r[P2]=P4"),
/* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
/* 74 */ "Null" OpHelp("r[P2..P3]=NULL"),
/* 75 */ "SoftNull" OpHelp("r[P1]=NULL"),
/* 76 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
/* 77 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
/* 78 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
/* 79 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
/* 80 */ "SCopy" OpHelp("r[P2]=r[P1]"),
/* 81 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
/* 82 */ "FkCheck" OpHelp(""),
/* 83 */ "ResultRow" OpHelp("output=r[P1@P2]"),
/* 84 */ "CollSeq" OpHelp(""),
/* 85 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
/* 86 */ "RealAffinity" OpHelp(""),
/* 87 */ "Cast" OpHelp("affinity(r[P1])"),
/* 88 */ "Permutation" OpHelp(""),
/* 89 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 90 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
/* 91 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
/* 92 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
/* 93 */ "Column" OpHelp("r[P3]=PX"),
/* 94 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
/* 95 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
/* 96 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
/* 97 */ "Count" OpHelp("r[P2]=count()"),
/* 98 */ "ReadCookie" OpHelp(""),
/* 99 */ "SetCookie" OpHelp(""),
/* 100 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
/* 101 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
/* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
/* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
/* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
/* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
/* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
/* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
/* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
/* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
/* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
/* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
/* 112 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
/* 113 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 114 */ "OpenDup" OpHelp(""),
/* 115 */ "OpenAutoindex" OpHelp("nColumn=P2"),
/* 116 */ "String8" OpHelp("r[P2]='P4'"),
/* 117 */ "OpenEphemeral" OpHelp("nColumn=P2"),
/* 118 */ "SorterOpen" OpHelp(""),
/* 119 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 120 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
/* 121 */ "Close" OpHelp(""),
/* 122 */ "ColumnsUsed" OpHelp(""),
/* 123 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
/* 124 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
/* 125 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
/* 126 */ "NewRowid" OpHelp("r[P2]=rowid"),
/* 127 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
/* 128 */ "RowCell" OpHelp(""),
/* 129 */ "Delete" OpHelp(""),
/* 130 */ "ResetCount" OpHelp(""),
/* 131 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
/* 132 */ "SorterData" OpHelp("r[P2]=data"),
/* 133 */ "RowData" OpHelp("r[P2]=data"),
/* 134 */ "Rowid" OpHelp("r[P2]=rowid"),
/* 135 */ "NullRow" OpHelp(""),
/* 136 */ "SeekEnd" OpHelp(""),
/* 137 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 138 */ "SorterInsert" OpHelp("key=r[P2]"),
/* 139 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
/* 140 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 141 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 142 */ "FinishSeek" OpHelp(""),
/* 143 */ "Destroy" OpHelp(""),
/* 144 */ "Clear" OpHelp(""),
/* 145 */ "ResetSorter" OpHelp(""),
/* 146 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
/* 147 */ "SqlExec" OpHelp(""),
/* 148 */ "ParseSchema" OpHelp(""),
/* 149 */ "LoadAnalysis" OpHelp(""),
/* 150 */ "DropTable" OpHelp(""),
/* 151 */ "DropIndex" OpHelp(""),
/* 152 */ "Real" OpHelp("r[P2]=P4"),
/* 153 */ "DropTrigger" OpHelp(""),
/* 154 */ "IntegrityCk" OpHelp(""),
/* 155 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
/* 156 */ "Param" OpHelp(""),
/* 157 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
/* 158 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
/* 159 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
/* 160 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
/* 161 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 162 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 163 */ "AggValue" OpHelp("r[P3]=value N=P2"),
/* 164 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
/* 165 */ "Expire" OpHelp(""),
/* 166 */ "CursorLock" OpHelp(""),
/* 167 */ "CursorUnlock" OpHelp(""),
/* 168 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
/* 169 */ "VBegin" OpHelp(""),
/* 170 */ "VCreate" OpHelp(""),
/* 171 */ "VDestroy" OpHelp(""),
/* 172 */ "VOpen" OpHelp(""),
/* 173 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 174 */ "VRename" OpHelp(""),
/* 175 */ "Pagecount" OpHelp(""),
/* 176 */ "MaxPgcnt" OpHelp(""),
/* 177 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
/* 178 */ "Trace" OpHelp(""),
/* 179 */ "CursorHint" OpHelp(""),
/* 180 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
/* 181 */ "Noop" OpHelp(""),
/* 182 */ "Explain" OpHelp(""),
/* 183 */ "Abortable" OpHelp(""),
};
return azName[i];
}
#endif
/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
|
| ︙ | ︙ | |||
38026 38027 38028 38029 38030 38031 38032 |
}else{
pFile->ctrlFlags |= mask;
}
}
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
| > | > | 38240 38241 38242 38243 38244 38245 38246 38247 38248 38249 38250 38251 38252 38253 38254 38255 38256 |
}else{
pFile->ctrlFlags |= mask;
}
}
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
#ifndef SQLITE_OMIT_WAL
static int unixFcntlExternalReader(unixFile*, int*);
#endif
/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
|
| ︙ | ︙ | |||
38145 38146 38147 38148 38149 38150 38151 38152 38153 38154 38155 38156 38157 38158 38159 |
case SQLITE_FCNTL_SET_LOCKPROXYFILE:
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
case SQLITE_FCNTL_EXTERNAL_READER: {
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
}
}
return SQLITE_NOTFOUND;
}
/*
** If pFd->sectorSize is non-zero when this function is called, it is a
| > > > > > | 38361 38362 38363 38364 38365 38366 38367 38368 38369 38370 38371 38372 38373 38374 38375 38376 38377 38378 38379 38380 |
case SQLITE_FCNTL_SET_LOCKPROXYFILE:
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
case SQLITE_FCNTL_EXTERNAL_READER: {
#ifndef SQLITE_OMIT_WAL
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
*(int*)pArg = 0;
return SQLITE_OK;
#endif
}
}
return SQLITE_NOTFOUND;
}
/*
** If pFd->sectorSize is non-zero when this function is called, it is a
|
| ︙ | ︙ | |||
39865 39866 39867 39868 39869 39870 39871 39872 39873 39874 39875 39876 39877 |
}else{
pId->pMethods = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
return rc;
}
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
| > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < | | | 40086 40087 40088 40089 40090 40091 40092 40093 40094 40095 40096 40097 40098 40099 40100 40101 40102 40103 40104 40105 40106 40107 40108 40109 40110 40111 40112 40113 40114 40115 40116 40117 40118 40119 40120 40121 40122 40123 40124 40125 40126 40127 40128 40129 40130 40131 40132 40133 40134 40135 40136 40137 40138 40139 |
}else{
pId->pMethods = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
return rc;
}
/*
** Directories to consider for temp files.
*/
static const char *azTempDirs[] = {
0,
0,
"/var/tmp",
"/usr/tmp",
"/tmp",
"."
};
/*
** Initialize first two members of azTempDirs[] array.
*/
static void unixTempFileInit(void){
azTempDirs[0] = getenv("SQLITE_TMPDIR");
azTempDirs[1] = getenv("TMPDIR");
}
/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
unsigned int i = 0;
struct stat buf;
const char *zDir = sqlite3_temp_directory;
while(1){
if( zDir!=0
&& osStat(zDir, &buf)==0
&& S_ISDIR(buf.st_mode)
&& osAccess(zDir, 03)==0
){
return zDir;
}
if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
zDir = azTempDirs[i++];
}
return 0;
}
/*
** Create a temporary file name in zBuf. zBuf must be allocated
** by the calling process and must be big enough to hold at least
|
| ︙ | ︙ | |||
40199 40200 40201 40202 40203 40204 40205 40206 40207 40208 40209 40210 40211 40212 |
** are harmless.
*/
if( randomnessPid!=osGetpid(0) ){
randomnessPid = osGetpid(0);
sqlite3_randomness(0,0);
}
memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){
UnixUnusedFd *pUnused;
pUnused = findReusableFd(zName, flags);
if( pUnused ){
fd = pUnused->fd;
}else{
| > > > > > | 40430 40431 40432 40433 40434 40435 40436 40437 40438 40439 40440 40441 40442 40443 40444 40445 40446 40447 40448 |
** are harmless.
*/
if( randomnessPid!=osGetpid(0) ){
randomnessPid = osGetpid(0);
sqlite3_randomness(0,0);
}
memset(p, 0, sizeof(unixFile));
#ifdef SQLITE_ASSERT_NO_FILES
/* Applications that never read or write a persistent disk files */
assert( zName==0 );
#endif
if( eType==SQLITE_OPEN_MAIN_DB ){
UnixUnusedFd *pUnused;
pUnused = findReusableFd(zName, flags);
if( pUnused ){
fd = pUnused->fd;
}else{
|
| ︙ | ︙ | |||
40260 40261 40262 40263 40264 40265 40266 |
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
assert( !isExclusive || (openFlags & O_CREAT)!=0 );
if( fd<0 ){
if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
/* If unable to create a journal because the directory is not
** writable, change the error code to indicate that. */
rc = SQLITE_READONLY_DIRECTORY;
| < < | 40496 40497 40498 40499 40500 40501 40502 40503 40504 40505 40506 40507 40508 40509 |
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
assert( !isExclusive || (openFlags & O_CREAT)!=0 );
if( fd<0 ){
if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
/* If unable to create a journal because the directory is not
** writable, change the error code to indicate that. */
rc = SQLITE_READONLY_DIRECTORY;
}else if( errno!=EISDIR && isReadWrite ){
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY;
openFlags |= O_RDONLY;
isReadonly = 1;
|
| ︙ | ︙ | |||
42162 42163 42164 42165 42166 42167 42168 42169 42170 42171 42172 42173 42174 42175 | ** READ-2 UNIX_SHM_BASE+5 125 ** READ-3 UNIX_SHM_BASE+6 126 ** READ-4 UNIX_SHM_BASE+7 127 ** DMS UNIX_SHM_BASE+8 128 */ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ #endif return SQLITE_OK; } /* ** Shutdown the operating system interface. ** | > > > | 42396 42397 42398 42399 42400 42401 42402 42403 42404 42405 42406 42407 42408 42409 42410 42411 42412 | ** READ-2 UNIX_SHM_BASE+5 125 ** READ-3 UNIX_SHM_BASE+6 126 ** READ-4 UNIX_SHM_BASE+7 127 ** DMS UNIX_SHM_BASE+8 128 */ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */ #endif /* Initialize temp file dir array. */ unixTempFileInit(); return SQLITE_OK; } /* ** Shutdown the operating system interface. ** |
| ︙ | ︙ | |||
48613 48614 48615 48616 48617 48618 48619 |
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
| | | 48850 48851 48852 48853 48854 48855 48856 48857 48858 48859 48860 48861 48862 48863 48864 |
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
unsigned char *pNew;
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
return SQLITE_FULL;
}
if( newSz>p->szMax ){
return SQLITE_FULL;
}
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
|
| ︙ | ︙ | |||
48672 48673 48674 48675 48676 48677 48678 |
** support WAL mode) the truncate() method is only used to reduce
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_OK;
memdbEnter(p);
| | > | | 48909 48910 48911 48912 48913 48914 48915 48916 48917 48918 48919 48920 48921 48922 48923 48924 48925 |
** support WAL mode) the truncate() method is only used to reduce
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_OK;
memdbEnter(p);
if( size>p->sz ){
/* This can only happen with a corrupt wal mode db */
rc = SQLITE_CORRUPT;
}else{
p->sz = size;
}
memdbLeave(p);
return rc;
}
|
| ︙ | ︙ | |||
48812 48813 48814 48815 48816 48817 48818 |
sqlite3_file *pFile,
sqlite3_int64 iOfst,
int iAmt,
void **pp
){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
| | | 49050 49051 49052 49053 49054 49055 49056 49057 49058 49059 49060 49061 49062 49063 49064 |
sqlite3_file *pFile,
sqlite3_int64 iOfst,
int iAmt,
void **pp
){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
memdbLeave(p);
return SQLITE_OK;
|
| ︙ | ︙ | |||
48846 48847 48848 48849 48850 48851 48852 |
sqlite3_file *pFd,
int flags,
int *pOutFlags
){
MemFile *pFile = (MemFile*)pFd;
MemStore *p = 0;
int szName;
| < | | | 49084 49085 49086 49087 49088 49089 49090 49091 49092 49093 49094 49095 49096 49097 49098 49099 |
sqlite3_file *pFd,
int flags,
int *pOutFlags
){
MemFile *pFile = (MemFile*)pFd;
MemStore *p = 0;
int szName;
UNUSED_PARAMETER(pVfs);
memset(pFile, 0, sizeof(*pFile));
szName = sqlite3Strlen30(zName);
if( szName>1 && zName[0]=='/' ){
int i;
#ifndef SQLITE_MUTEX_OMIT
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
|
| ︙ | ︙ | |||
48908 48909 48910 48911 48912 48913 48914 |
return SQLITE_NOMEM;
}
memset(p, 0, sizeof(*p));
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
}
pFile->pStore = p;
| | | > | 49145 49146 49147 49148 49149 49150 49151 49152 49153 49154 49155 49156 49157 49158 49159 49160 49161 |
return SQLITE_NOMEM;
}
memset(p, 0, sizeof(*p));
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
}
pFile->pStore = p;
if( pOutFlags!=0 ){
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
}
pFd->pMethods = &memdb_io_methods;
memdbLeave(p);
return SQLITE_OK;
}
#if 0 /* Only used to delete rollback journals, super-journals, and WAL
** files, none of which exist in memdb. So this routine is never used */
|
| ︙ | ︙ | |||
49574 49575 49576 49577 49578 49579 49580 | if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ sqlite3BitvecSet(0, 1); sqlite3BitvecClear(0, 1, pTmpSpace); /* Run the program */ | | | 49812 49813 49814 49815 49816 49817 49818 49819 49820 49821 49822 49823 49824 49825 49826 |
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
/* NULL pBitvec tests */
sqlite3BitvecSet(0, 1);
sqlite3BitvecClear(0, 1, pTmpSpace);
/* Run the program */
pc = i = 0;
while( (op = aOp[pc])!=0 ){
switch( op ){
case 1:
case 2:
case 5: {
nx = 4;
i = aOp[pc+2] - 1;
|
| ︙ | ︙ | |||
53104 53105 53106 53107 53108 53109 53110 53111 53112 53113 53114 53115 53116 53117 | u8 extraSync; /* sync directory after journal delete */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ u8 walSyncFlags; /* See description above */ u8 tempFile; /* zFilename is a temporary or immutable file */ u8 noLock; /* Do not lock (except in WAL mode) */ u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ /************************************************************************** ** The following block contains those class members that change during ** routine operation. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a ** significant mode change (such as changing the page_size, locking_mode, ** or the journal_mode). From another view, these class members describe | > | 53342 53343 53344 53345 53346 53347 53348 53349 53350 53351 53352 53353 53354 53355 53356 | u8 extraSync; /* sync directory after journal delete */ u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */ u8 walSyncFlags; /* See description above */ u8 tempFile; /* zFilename is a temporary or immutable file */ u8 noLock; /* Do not lock (except in WAL mode) */ u8 readOnly; /* True for a read-only database */ u8 memDb; /* True to inhibit all file I/O */ u8 memVfs; /* VFS-implemented memory database */ /************************************************************************** ** The following block contains those class members that change during ** routine operation. Class members not in this block are either fixed ** when the pager is first created or else only change when there is a ** significant mode change (such as changing the page_size, locking_mode, ** or the journal_mode). From another view, these class members describe |
| ︙ | ︙ | |||
55498 55499 55500 55501 55502 55503 55504 55505 55506 55507 55508 55509 55510 55511 |
**
** This is an unconditional update. See also the pager_incr_changecounter()
** routine which only updates the change-counter if the update is actually
** needed, as determined by the pPager->changeCountDone state variable.
*/
static void pager_write_changecounter(PgHdr *pPg){
u32 change_counter;
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
put32bits(((char*)pPg->pData)+24, change_counter);
/* Also store the SQLite version number in bytes 96..99 and in
** bytes 92..95 store the change counter for which the version number
| > | 55737 55738 55739 55740 55741 55742 55743 55744 55745 55746 55747 55748 55749 55750 55751 |
**
** This is an unconditional update. See also the pager_incr_changecounter()
** routine which only updates the change-counter if the update is actually
** needed, as determined by the pPager->changeCountDone state variable.
*/
static void pager_write_changecounter(PgHdr *pPg){
u32 change_counter;
if( NEVER(pPg==0) ) return;
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
put32bits(((char*)pPg->pData)+24, change_counter);
/* Also store the SQLite version number in bytes 96..99 and in
** bytes 92..95 store the change counter for which the version number
|
| ︙ | ︙ | |||
57345 57346 57347 57348 57349 57350 57351 |
/* Open the pager file.
*/
if( zFilename && zFilename[0] ){
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
#ifndef SQLITE_OMIT_DESERIALIZE
| | | 57585 57586 57587 57588 57589 57590 57591 57592 57593 57594 57595 57596 57597 57598 57599 |
/* Open the pager file.
*/
if( zFilename && zFilename[0] ){
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
#ifndef SQLITE_OMIT_DESERIALIZE
pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
/* If the file was successfully opened for read/write access,
** choose a default page size in case we have to create the
** database file. The default page size is the maximum of:
**
|
| ︙ | ︙ | |||
59282 59283 59284 59285 59286 59287 59288 |
}
}
/*
** Return true if this is an in-memory or temp-file backed pager.
*/
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
| | | 59522 59523 59524 59525 59526 59527 59528 59529 59530 59531 59532 59533 59534 59535 59536 |
}
}
/*
** Return true if this is an in-memory or temp-file backed pager.
*/
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager *pPager){
return pPager->tempFile || pPager->memVfs;
}
/*
** Check that there are at least nSavepoint savepoints open. If there are
** currently less than nSavepoints open, then open one or more savepoints
** to make up the difference. If the number of savepoints is already
** equal to nSavepoint, then this function is a no-op.
|
| ︙ | ︙ | |||
59602 59603 59604 59605 59606 59607 59608 |
** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
pPg->flags &= ~PGHDR_NEED_SYNC;
pPgOld = sqlite3PagerLookup(pPager, pgno);
assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
if( pPgOld ){
| | | 59842 59843 59844 59845 59846 59847 59848 59849 59850 59851 59852 59853 59854 59855 59856 |
** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
pPg->flags &= ~PGHDR_NEED_SYNC;
pPgOld = sqlite3PagerLookup(pPager, pgno);
assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
if( pPgOld ){
if( NEVER(pPgOld->nRef>1) ){
sqlite3PagerUnrefNotNull(pPgOld);
return SQLITE_CORRUPT_BKPT;
}
pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
if( pPager->tempFile ){
/* Do not discard pages from an in-memory database since we might
** need to rollback later. Just move the page out of the way. */
|
| ︙ | ︙ | |||
60807 60808 60809 60810 60811 60812 60813 | ** numbered from zero. ** ** If the wal-index is currently smaller the iPage pages then the size ** of the wal-index might be increased, but only if it is safe to do ** so. It is safe to enlarge the wal-index if pWal->writeLock is true ** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE. ** | | > | | > > > | 61047 61048 61049 61050 61051 61052 61053 61054 61055 61056 61057 61058 61059 61060 61061 61062 61063 61064 61065 61066 61067 |
** numbered from zero.
**
** If the wal-index is currently smaller the iPage pages then the size
** of the wal-index might be increased, but only if it is safe to do
** so. It is safe to enlarge the wal-index if pWal->writeLock is true
** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
**
** Three possible result scenarios:
**
** (1) rc==SQLITE_OK and *ppPage==Requested-Wal-Index-Page
** (2) rc>=SQLITE_ERROR and *ppPage==NULL
** (3) rc==SQLITE_OK and *ppPage==NULL // only if iPage==0
**
** Scenario (3) can only occur when pWal->writeLock is false and iPage==0
*/
static SQLITE_NOINLINE int walIndexPageRealloc(
Wal *pWal, /* The WAL context */
int iPage, /* The page we seek */
volatile u32 **ppPage /* Write the page pointer here */
){
int rc = SQLITE_OK;
|
| ︙ | ︙ | |||
60842 60843 60844 60845 60846 60847 60848 |
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
| | > > | 61086 61087 61088 61089 61090 61091 61092 61093 61094 61095 61096 61097 61098 61099 61100 61101 61102 |
if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT;
}else{
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
assert( pWal->apWiData[iPage]!=0
|| rc!=SQLITE_OK
|| (pWal->writeLock==0 && iPage==0) );
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
if( rc==SQLITE_OK ){
if( iPage>0 && sqlite3FaultSim(600) ) rc = SQLITE_NOMEM;
}else if( (rc&0xff)==SQLITE_READONLY ){
pWal->readOnly |= WAL_SHM_RDONLY;
if( rc==SQLITE_READONLY ){
rc = SQLITE_OK;
|
| ︙ | ︙ | |||
61181 61182 61183 61184 61185 61186 61187 | ** ** Set output variable pLoc->aHash to point to the start of the hash table ** in the wal-index file. Set pLoc->iZero to one less than the frame ** number of the first frame indexed by this hash table. If a ** slot in the hash table is set to N, it refers to frame number ** (pLoc->iZero+N) in the log. ** | | | | > | | 61427 61428 61429 61430 61431 61432 61433 61434 61435 61436 61437 61438 61439 61440 61441 61442 61443 61444 61445 61446 61447 61448 61449 61450 61451 61452 61453 61454 61455 61456 61457 61458 61459 61460 61461 61462 61463 |
**
** Set output variable pLoc->aHash to point to the start of the hash table
** in the wal-index file. Set pLoc->iZero to one less than the frame
** number of the first frame indexed by this hash table. If a
** slot in the hash table is set to N, it refers to frame number
** (pLoc->iZero+N) in the log.
**
** Finally, set pLoc->aPgno so that pLoc->aPgno[0] is the page number of the
** first frame indexed by the hash table, frame (pLoc->iZero).
*/
static int walHashGet(
Wal *pWal, /* WAL handle */
int iHash, /* Find the iHash'th table */
WalHashLoc *pLoc /* OUT: Hash table location */
){
int rc; /* Return code */
rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
assert( rc==SQLITE_OK || iHash>0 );
if( pLoc->aPgno ){
pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
if( iHash==0 ){
pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
pLoc->iZero = 0;
}else{
pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
}
}else if( NEVER(rc==SQLITE_OK) ){
rc = SQLITE_ERROR;
}
return rc;
}
/*
** Return the number of the wal-index page that contains the hash-table
** and page-number array that contain entries corresponding to WAL frame
|
| ︙ | ︙ | |||
61284 61285 61286 61287 61288 61289 61290 |
sLoc.aHash[i] = 0;
}
}
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
| | > | | | | | 61531 61532 61533 61534 61535 61536 61537 61538 61539 61540 61541 61542 61543 61544 61545 61546 61547 61548 61549 61550 61551 61552 61553 61554 61555 61556 61557 61558 61559 61560 |
sLoc.aHash[i] = 0;
}
}
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit]);
assert( nByte>=0 );
memset((void *)&sLoc.aPgno[iLimit], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the every entry in the mapping region is still reachable
** via the hash table even after the cleanup.
*/
if( iLimit ){
int j; /* Loop counter */
int iKey; /* Hash key */
for(j=0; j<iLimit; j++){
for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
if( sLoc.aHash[iKey]==j+1 ) break;
}
assert( sLoc.aHash[iKey]==j+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
}
/*
|
| ︙ | ︙ | |||
61330 61331 61332 61333 61334 61335 61336 |
idx = iFrame - sLoc.iZero;
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
/* If this is the first entry to be added to this hash-table, zero the
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
| | | | | | | | | | < | 61578 61579 61580 61581 61582 61583 61584 61585 61586 61587 61588 61589 61590 61591 61592 61593 61594 61595 61596 61597 61598 61599 61600 61601 61602 61603 61604 61605 61606 61607 61608 61609 61610 61611 61612 61613 61614 61615 61616 61617 61618 61619 61620 61621 61622 61623 61624 61625 61626 61627 61628 61629 61630 61631 61632 61633 61634 61635 61636 61637 61638 61639 61640 61641 61642 61643 61644 |
idx = iFrame - sLoc.iZero;
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
/* If this is the first entry to be added to this hash-table, zero the
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
int nByte = (int)((u8*)&sLoc.aHash[HASHTABLE_NSLOT] - (u8*)sLoc.aPgno);
assert( nByte>=0 );
memset((void*)sLoc.aPgno, 0, nByte);
}
/* If the entry in aPgno[] is already set, then the previous writer
** must have exited unexpectedly in the middle of a transaction (after
** writing one or more dirty pages to the WAL to free up memory).
** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
if( sLoc.aPgno[idx-1] ){
walCleanupHash(pWal);
assert( !sLoc.aPgno[idx-1] );
}
/* Write the aPgno[] array entry and the hash-table slot. */
nCollide = idx;
for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
sLoc.aPgno[idx-1] = iPage;
AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
** the number of entries in the mapping region.
*/
{
int i; /* Loop counter */
int nEntry = 0; /* Number of entries in the hash table */
for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; }
assert( nEntry==idx );
}
/* Verify that the every entry in the mapping region is reachable
** via the hash table. This turns out to be a really, really expensive
** thing to check, so only do this occasionally - not on every
** iteration.
*/
if( (idx&0x3ff)==0 ){
int i; /* Loop counter */
for(i=0; i<idx; i++){
for(iKey=walHash(sLoc.aPgno[i]);
sLoc.aHash[iKey];
iKey=walNextHash(iKey)){
if( sLoc.aHash[iKey]==i+1 ) break;
}
assert( sLoc.aHash[iKey]==i+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
}
return rc;
}
/*
** Recover the wal-index by reading the write-ahead log file.
|
| ︙ | ︙ | |||
61505 61506 61507 61508 61509 61510 61511 |
for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){
u32 *aShare;
u32 iFrame; /* Index of last frame read */
u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE);
u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
u32 nHdr, nHdr32;
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
| > | | 61752 61753 61754 61755 61756 61757 61758 61759 61760 61761 61762 61763 61764 61765 61766 61767 |
for(iPg=0; iPg<=(u32)walFramePage(iLastFrame); iPg++){
u32 *aShare;
u32 iFrame; /* Index of last frame read */
u32 iLast = MIN(iLastFrame, HASHTABLE_NPAGE_ONE+iPg*HASHTABLE_NPAGE);
u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
u32 nHdr, nHdr32;
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
assert( aShare!=0 || rc!=SQLITE_OK );
if( aShare==0 ) break;
pWal->apWiData[iPg] = aPrivate;
for(iFrame=iFirst; iFrame<=iLast; iFrame++){
i64 iOffset = walFrameOffset(iFrame, szPage);
u32 pgno; /* Database page number for frame */
u32 nTruncate; /* dbsize field from frame header */
|
| ︙ | ︙ | |||
62002 62003 62004 62005 62006 62007 62008 |
rc = walHashGet(pWal, i, &sLoc);
if( rc==SQLITE_OK ){
int j; /* Counter variable */
int nEntry; /* Number of entries in this segment */
ht_slot *aIndex; /* Sorted index for this segment */
| < | 62250 62251 62252 62253 62254 62255 62256 62257 62258 62259 62260 62261 62262 62263 |
rc = walHashGet(pWal, i, &sLoc);
if( rc==SQLITE_OK ){
int j; /* Counter variable */
int nEntry; /* Number of entries in this segment */
ht_slot *aIndex; /* Sorted index for this segment */
if( (i+1)==nSegment ){
nEntry = (int)(iLast - sLoc.iZero);
}else{
nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno);
}
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero];
sLoc.iZero++;
|
| ︙ | ︙ | |||
63141 63142 63143 63144 63145 63146 63147 |
WalHashLoc sLoc; /* Hash table location */
u32 pgno; /* Page number in db file */
i64 iDbOff; /* Offset of db file entry */
i64 iWalOff; /* Offset of wal file entry */
rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
| > | | 63388 63389 63390 63391 63392 63393 63394 63395 63396 63397 63398 63399 63400 63401 63402 63403 |
WalHashLoc sLoc; /* Hash table location */
u32 pgno; /* Page number in db file */
i64 iDbOff; /* Offset of db file entry */
i64 iWalOff; /* Offset of wal file entry */
rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
assert( i - sLoc.iZero - 1 >=0 );
pgno = sLoc.aPgno[i-sLoc.iZero-1];
iDbOff = (i64)(pgno-1) * szPage;
if( iDbOff+szPage<=szDb ){
iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
if( rc==SQLITE_OK ){
|
| ︙ | ︙ | |||
63374 63375 63376 63377 63378 63379 63380 |
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
iKey = walHash(pgno);
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
| | | 63622 63623 63624 63625 63626 63627 63628 63629 63630 63631 63632 63633 63634 63635 63636 |
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
iKey = walHash(pgno);
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
if( (nCollide--)==0 ){
return SQLITE_CORRUPT_BKPT;
}
iKey = walNextHash(iKey);
|
| ︙ | ︙ | |||
64626 64627 64628 64629 64630 64631 64632 |
** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
| < | 64874 64875 64876 64877 64878 64879 64880 64881 64882 64883 64884 64885 64886 64887 |
** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
u8 intKey; /* True if table b-trees. False for index b-trees */
u8 intKeyLeaf; /* True if the leaf of an intKey table */
Pgno pgno; /* Page number for this page */
/* Only the first 8 bytes (above) are zeroed by pager.c when a new page
** is allocated. All fields that follow must be initialized before use */
u8 leaf; /* True if a leaf page */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
| ︙ | ︙ | |||
66868 66869 66870 66871 66872 66873 66874 |
}
if( iFree2 ){
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
sz2 = get2byte(&data[iFree2+2]);
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
| | | 67115 67116 67117 67118 67119 67120 67121 67122 67123 67124 67125 67126 67127 67128 67129 |
}
if( iFree2 ){
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
sz2 = get2byte(&data[iFree2+2]);
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
}else if( NEVER(iFree+sz>usableSize) ){
return SQLITE_CORRUPT_PAGE(pPage);
}
cbrk = top+sz;
assert( cbrk+(iFree-top) <= usableSize );
memmove(&data[cbrk], &data[top], iFree-top);
for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
|
| ︙ | ︙ | |||
68073 68074 68075 68076 68077 68078 68079 | } /* ** Make sure pBt->pTmpSpace points to an allocation of ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child ** pointer. */ | | > | > > > | > > > > > | > | | | | | | | | | | | | | | | < | | < < > | 68320 68321 68322 68323 68324 68325 68326 68327 68328 68329 68330 68331 68332 68333 68334 68335 68336 68337 68338 68339 68340 68341 68342 68343 68344 68345 68346 68347 68348 68349 68350 68351 68352 68353 68354 68355 68356 68357 68358 68359 68360 68361 68362 68363 68364 68365 |
}
/*
** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
assert( pBt!=0 );
assert( pBt->pTmpSpace==0 );
/* This routine is called only by btreeCursor() when allocating the
** first write cursor for the BtShared object */
assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
if( pBt->pTmpSpace==0 ){
BtCursor *pCur = pBt->pCursor;
pBt->pCursor = pCur->pNext; /* Unlink the cursor */
memset(pCur, 0, sizeof(*pCur));
return SQLITE_NOMEM_BKPT;
}
/* One of the uses of pBt->pTmpSpace is to format cells before
** inserting them into a leaf page (function fillInCell()). If
** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
** by the various routines that manipulate binary cells. Which
** can mean that fillInCell() only initializes the first 2 or 3
** bytes of pTmpSpace, but that the first 4 bytes are copied from
** it into a database page. This is not actually a problem, but it
** does cause a valgrind error when the 1 or 2 bytes of unitialized
** data is passed to system call write(). So to avoid this error,
** zero the first 4 bytes of temp space here.
**
** Also: Provide four bytes of initialized space before the
** beginning of pTmpSpace as an area available to prepend the
** left-child pointer to the beginning of a cell.
*/
memset(pBt->pTmpSpace, 0, 8);
pBt->pTmpSpace += 4;
return SQLITE_OK;
}
/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
if( pBt->pTmpSpace ){
|
| ︙ | ︙ | |||
68475 68476 68477 68478 68479 68480 68481 |
** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
MemPage *pPage1; /* Page 1 of the database file */
u32 nPage; /* Number of pages in the database */
u32 nPageFile = 0; /* Number of pages in the database file */
| < | | 68730 68731 68732 68733 68734 68735 68736 68737 68738 68739 68740 68741 68742 68743 68744 68745 68746 68747 68748 68749 68750 68751 68752 68753 68754 68755 |
** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
MemPage *pPage1; /* Page 1 of the database file */
u32 nPage; /* Number of pages in the database */
u32 nPageFile = 0; /* Number of pages in the database file */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pBt->pPage1==0 );
rc = sqlite3PagerSharedLock(pBt->pPager);
if( rc!=SQLITE_OK ) return rc;
rc = btreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
nPage = get4byte(28+(u8*)pPage1->aData);
sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
}
if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){
nPage = 0;
}
|
| ︙ | ︙ | |||
69320 69321 69322 69323 69324 69325 69326 | sqlite3BtreeLeave(p); return rc; } /* ** This routine is called prior to sqlite3PagerCommit when a transaction ** is committed for an auto-vacuum database. | < < < < < | | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > | | > | | > | 69574 69575 69576 69577 69578 69579 69580 69581 69582 69583 69584 69585 69586 69587 69588 69589 69590 69591 69592 69593 69594 69595 69596 69597 69598 69599 69600 69601 69602 69603 69604 69605 69606 69607 69608 69609 69610 69611 69612 69613 69614 69615 69616 69617 69618 69619 69620 69621 69622 69623 69624 69625 69626 69627 69628 69629 69630 69631 69632 69633 69634 69635 69636 69637 69638 69639 69640 69641 69642 69643 69644 69645 69646 69647 69648 69649 69650 69651 69652 69653 69654 69655 69656 |
sqlite3BtreeLeave(p);
return rc;
}
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
** is committed for an auto-vacuum database.
*/
static int autoVacuumCommit(Btree *p){
int rc = SQLITE_OK;
Pager *pPager;
BtShared *pBt;
sqlite3 *db;
VVA_ONLY( int nRef );
assert( p!=0 );
pBt = p->pBt;
pPager = pBt->pPager;
VVA_ONLY( nRef = sqlite3PagerRefcount(pPager); )
assert( sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
assert(pBt->autoVacuum);
if( !pBt->incrVacuum ){
Pgno nFin; /* Number of pages in database after autovacuuming */
Pgno nFree; /* Number of pages on the freelist initially */
Pgno nVac; /* Number of pages to vacuum */
Pgno iFree; /* The next page to be freed */
Pgno nOrig; /* Database size before freeing */
nOrig = btreePagecount(pBt);
if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){
/* It is not possible to create a database for which the final page
** is either a pointer-map page or the pending-byte page. If one
** is encountered, this indicates corruption.
*/
return SQLITE_CORRUPT_BKPT;
}
nFree = get4byte(&pBt->pPage1->aData[36]);
db = p->db;
if( db->xAutovacPages ){
int iDb;
for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
if( db->aDb[iDb].pBt==p ) break;
}
nVac = db->xAutovacPages(
db->pAutovacPagesArg,
db->aDb[iDb].zDbSName,
nOrig,
nFree,
pBt->pageSize
);
if( nVac>nFree ){
nVac = nFree;
}
if( nVac==0 ){
return SQLITE_OK;
}
}else{
nVac = nFree;
}
nFin = finalDbSize(pBt, nOrig, nVac);
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
if( nFin<nOrig ){
rc = saveAllCursors(pBt, 0, 0);
}
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( nVac==nFree ){
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
}
put4byte(&pBt->pPage1->aData[28], nFin);
pBt->bDoTruncate = 1;
pBt->nPage = nFin;
}
if( rc!=SQLITE_OK ){
sqlite3PagerRollback(pPager);
}
|
| ︙ | ︙ | |||
69412 69413 69414 69415 69416 69417 69418 |
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
int rc = SQLITE_OK;
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
| | | 69693 69694 69695 69696 69697 69698 69699 69700 69701 69702 69703 69704 69705 69706 69707 |
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
int rc = SQLITE_OK;
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
rc = autoVacuumCommit(p);
if( rc!=SQLITE_OK ){
sqlite3BtreeLeave(p);
return rc;
}
}
if( pBt->bDoTruncate ){
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
|
| ︙ | ︙ | |||
69811 69812 69813 69814 69815 69816 69817 | /* Assert that the caller has opened the required transaction. */ assert( p->inTrans>TRANS_NONE ); assert( wrFlag==0 || p->inTrans==TRANS_WRITE ); assert( pBt->pPage1 && pBt->pPage1->aData ); assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); | < < < < | < | > > > | > > > > | 70092 70093 70094 70095 70096 70097 70098 70099 70100 70101 70102 70103 70104 70105 70106 70107 70108 70109 70110 70111 70112 70113 70114 70115 70116 70117 70118 70119 70120 70121 70122 70123 70124 70125 70126 70127 70128 70129 70130 70131 70132 70133 70134 70135 70136 70137 70138 70139 70140 |
/* Assert that the caller has opened the required transaction. */
assert( p->inTrans>TRANS_NONE );
assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
assert( pBt->pPage1 && pBt->pPage1->aData );
assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
if( iTable<=1 ){
if( iTable<1 ){
return SQLITE_CORRUPT_BKPT;
}else if( btreePagecount(pBt)==0 ){
assert( wrFlag==0 );
iTable = 0;
}
}
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
pCur->pgnoRoot = iTable;
pCur->iPage = -1;
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
pCur->curFlags = 0;
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
pCur->curFlags = BTCF_Multiple;
}
}
pCur->eState = CURSOR_INVALID;
pCur->pNext = pBt->pCursor;
pBt->pCursor = pCur;
if( wrFlag ){
pCur->curFlags |= BTCF_WriteFlag;
pCur->curPagerFlags = 0;
if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
}else{
pCur->curPagerFlags = PAGER_GET_READONLY;
}
return SQLITE_OK;
}
static int btreeCursorWithLock(
Btree *p, /* The btree */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
|
| ︙ | ︙ | |||
70217 70218 70219 70220 70221 70222 70223 | #ifdef SQLITE_DIRECT_OVERFLOW_READ unsigned char * const pBufStart = pBuf; /* Start of original out buffer */ #endif assert( pPage ); assert( eOp==0 || eOp==1 ); assert( pCur->eState==CURSOR_VALID ); | | > > | 70500 70501 70502 70503 70504 70505 70506 70507 70508 70509 70510 70511 70512 70513 70514 70515 70516 |
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
#endif
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
if( pCur->ix>=pPage->nCell ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
|
| ︙ | ︙ | |||
70404 70405 70406 70407 70408 70409 70410 |
** wrong. An error is returned if "offset+amt" is larger than
** the available payload.
*/
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->pPage );
| < | 70689 70690 70691 70692 70693 70694 70695 70696 70697 70698 70699 70700 70701 70702 |
** wrong. An error is returned if "offset+amt" is larger than
** the available payload.
*/
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->pPage );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
** This variant of sqlite3BtreePayload() works even if the cursor has not
** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
** interface.
|
| ︙ | ︙ | |||
70466 70467 70468 70469 70470 70471 70472 |
u32 *pAmt /* Write the number of available bytes here */
){
int amt;
assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
| | | 70750 70751 70752 70753 70754 70755 70756 70757 70758 70759 70760 70761 70762 70763 70764 |
u32 *pAmt /* Write the number of available bytes here */
){
int amt;
assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
amt = pCur->info.nLocal;
if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
/* There is too little space on the page for the expected amount
** of local content. Database must be corrupt. */
|
| ︙ | ︙ | |||
71252 71253 71254 71255 71256 71257 71258 |
** in a corrupt database file where the table being DELETE-ed from
** has pages in common with the table being queried. See TH3
** module cov1/btree78.test testcase 220 (2018-06-08) for an
** example. */
return SQLITE_CORRUPT_BKPT;
}
| < < < < < < < < < < | 71536 71537 71538 71539 71540 71541 71542 71543 71544 71545 71546 71547 71548 71549 |
** in a corrupt database file where the table being DELETE-ed from
** has pages in common with the table being queried. See TH3
** module cov1/btree78.test testcase 220 (2018-06-08) for an
** example. */
return SQLITE_CORRUPT_BKPT;
}
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
if( rc ) return rc;
return moveToLeftmost(pCur);
}
do{
|
| ︙ | ︙ | |||
71749 71750 71751 71752 71753 71754 71755 | int rc; /* Return Code */ u32 nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( CORRUPT_DB || iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); | | | 72023 72024 72025 72026 72027 72028 72029 72030 72031 72032 72033 72034 72035 72036 72037 |
int rc; /* Return Code */
u32 nFree; /* Initial number of pages on free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
assert( CORRUPT_DB || iPage>1 );
assert( !pMemPage || pMemPage->pgno==iPage );
if( NEVER(iPage<2) || iPage>pBt->nPage ){
return SQLITE_CORRUPT_BKPT;
}
if( pMemPage ){
pPage = pMemPage;
sqlite3PagerRef(pPage->pDbPage);
}else{
pPage = btreePageLookup(pBt, iPage);
|
| ︙ | ︙ | |||
73067 73068 73069 73070 73071 73072 73073 | int szNew[NB+2]; /* Combined size of cells placed on i-th page */ u8 *aSpace1; /* Space for copies of dividers cells */ Pgno pgno; /* Temp var to store a page number in */ u8 abDone[NB+2]; /* True after i'th new page is populated */ Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ | | | < | 73341 73342 73343 73344 73345 73346 73347 73348 73349 73350 73351 73352 73353 73354 73355 73356 73357 73358 | int szNew[NB+2]; /* Combined size of cells placed on i-th page */ u8 *aSpace1; /* Space for copies of dividers cells */ Pgno pgno; /* Temp var to store a page number in */ u8 abDone[NB+2]; /* True after i'th new page is populated */ Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ CellArray b; /* Parsed information on cells being balanced */ memset(abDone, 0, sizeof(abDone)); memset(&b, 0, sizeof(b)); pBt = pParent->pBt; assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); /* At this point pParent may have at most one overflow cell. And if ** this overflow cell is present, it must be the cell with ** index iParentIdx. This scenario comes about when this function |
| ︙ | ︙ | |||
73882 73883 73884 73885 73886 73887 73888 | return SQLITE_OK; } /* ** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid ** on the same B-tree as pCur. ** | | | 74155 74156 74157 74158 74159 74160 74161 74162 74163 74164 74165 74166 74167 74168 74169 |
return SQLITE_OK;
}
/*
** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
** on the same B-tree as pCur.
**
** This can occur if a database is corrupt with two or more SQL tables
** pointing to the same b-tree. If an insert occurs on one SQL table
** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
** table linked to the same b-tree. If the secondary insert causes a
** rebalance, that can change content out from under the cursor on the
** first SQL table, violating invariants on the first insert.
*/
static int anotherValidCursor(BtCursor *pCur){
|
| ︙ | ︙ | |||
74351 74352 74353 74354 74355 74356 74357 |
}
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->ix;
if( loc==0 ){
CellInfo info;
| | > > > | 74624 74625 74626 74627 74628 74629 74630 74631 74632 74633 74634 74635 74636 74637 74638 74639 74640 74641 |
}
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->ix;
if( loc==0 ){
CellInfo info;
assert( idx>=0 );
if( idx>=pPage->nCell ){
return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
}
oldCell = findCell(pPage, idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
|
| ︙ | ︙ | |||
74937 74938 74939 74940 74941 74942 74943 |
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
if( rc ) return rc;
| > | > < | 75213 75214 75215 75216 75217 75218 75219 75220 75221 75222 75223 75224 75225 75226 75227 75228 75229 75230 75231 75232 |
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
if( rc ) return rc;
if( (pBt->openFlags & BTREE_SINGLE)==0
&& sqlite3PagerPageRefcount(pPage->pDbPage)!=1
){
rc = SQLITE_CORRUPT_BKPT;
goto cleardatabasepage_out;
}
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
|
| ︙ | ︙ | |||
74968 74969 74970 74971 74972 74973 74974 |
if( freePageFlag ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
}
cleardatabasepage_out:
| < | 75245 75246 75247 75248 75249 75250 75251 75252 75253 75254 75255 75256 75257 75258 |
if( freePageFlag ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
}
cleardatabasepage_out:
releasePage(pPage);
return rc;
}
/*
** Delete all information from a single table in the database. iTable is
** the page number of the root of the table. After this routine returns,
|
| ︙ | ︙ | |||
75047 75048 75049 75050 75051 75052 75053 |
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
if( iTable>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
| < < | > > | 75323 75324 75325 75326 75327 75328 75329 75330 75331 75332 75333 75334 75335 75336 75337 75338 75339 75340 |
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
assert( iTable>=2 );
if( iTable>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3BtreeClearTable(p, iTable, 0);
if( rc ) return rc;
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( NEVER(rc) ){
releasePage(pPage);
return rc;
}
*piMoved = 0;
#ifdef SQLITE_OMIT_AUTOVACUUM
|
| ︙ | ︙ | |||
77207 77208 77209 77210 77211 77212 77213 77214 77215 77216 77217 77218 77219 77220 |
** SQLITE_NOMEM may be returned if a malloc() fails during conversion
** between formats.
*/
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
| > | 77483 77484 77485 77486 77487 77488 77489 77490 77491 77492 77493 77494 77495 77496 77497 |
** SQLITE_NOMEM may be returned if a malloc() fails during conversion
** between formats.
*/
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
assert( pMem!=0 );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
| ︙ | ︙ | |||
77339 77340 77341 77342 77343 77344 77345 77346 77347 77348 77349 77350 77351 77352 |
/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
int rc = vdbeMemAddTerminator(pMem);
if( rc ) return rc;
| > | 77616 77617 77618 77619 77620 77621 77622 77623 77624 77625 77626 77627 77628 77629 77630 |
/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
int rc = vdbeMemAddTerminator(pMem);
if( rc ) return rc;
|
| ︙ | ︙ | |||
77363 77364 77365 77366 77367 77368 77369 77370 77371 77372 77373 77374 77375 77376 77377 77378 77379 77380 77381 77382 77383 77384 77385 77386 77387 77388 77389 77390 77391 77392 77393 77394 77395 77396 77397 77398 77399 77400 77401 77402 77403 |
/*
** If the given Mem* has a zero-filled tail, turn it into an ordinary
** blob stored in dynamically allocated space.
*/
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
int nByte;
assert( pMem->flags & MEM_Zero );
assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) );
testcase( sqlite3_value_nochange(pMem) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
nByte = pMem->n + pMem->u.nZero;
if( nByte<=0 ){
if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
nByte = 1;
}
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM_BKPT;
}
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
pMem->n += pMem->u.nZero;
pMem->flags &= ~(MEM_Zero|MEM_Term);
return SQLITE_OK;
}
#endif
/*
** Make sure the given Mem is \u0000 terminated.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){
return SQLITE_OK; /* Nothing to do */
}else{
return vdbeMemAddTerminator(pMem);
| > > > > | 77641 77642 77643 77644 77645 77646 77647 77648 77649 77650 77651 77652 77653 77654 77655 77656 77657 77658 77659 77660 77661 77662 77663 77664 77665 77666 77667 77668 77669 77670 77671 77672 77673 77674 77675 77676 77677 77678 77679 77680 77681 77682 77683 77684 77685 |
/*
** If the given Mem* has a zero-filled tail, turn it into an ordinary
** blob stored in dynamically allocated space.
*/
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
int nByte;
assert( pMem!=0 );
assert( pMem->flags & MEM_Zero );
assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) );
testcase( sqlite3_value_nochange(pMem) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
nByte = pMem->n + pMem->u.nZero;
if( nByte<=0 ){
if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
nByte = 1;
}
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM_BKPT;
}
assert( pMem->z!=0 );
assert( sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte );
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
pMem->n += pMem->u.nZero;
pMem->flags &= ~(MEM_Zero|MEM_Term);
return SQLITE_OK;
}
#endif
/*
** Make sure the given Mem is \u0000 terminated.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
if( (pMem->flags & (MEM_Term|MEM_Str))!=MEM_Str ){
return SQLITE_OK; /* Nothing to do */
}else{
return vdbeMemAddTerminator(pMem);
|
| ︙ | ︙ | |||
77417 77418 77419 77420 77421 77422 77423 77424 77425 77426 77427 77428 77429 77430 |
** sqlite3_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the latter is an internal programming error.
*/
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
const int nByte = 32;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(pMem->flags&MEM_Zero) );
assert( !(pMem->flags&(MEM_Str|MEM_Blob)) );
assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
| > | 77699 77700 77701 77702 77703 77704 77705 77706 77707 77708 77709 77710 77711 77712 77713 |
** sqlite3_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the latter is an internal programming error.
*/
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
const int nByte = 32;
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(pMem->flags&MEM_Zero) );
assert( !(pMem->flags&(MEM_Str|MEM_Blob)) );
assert( pMem->flags&(MEM_Int|MEM_Real|MEM_IntReal) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
|
| ︙ | ︙ | |||
77452 77453 77454 77455 77456 77457 77458 77459 77460 77461 77462 77463 77464 77465 |
** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
** otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
Mem t;
assert( pFunc!=0 );
assert( pFunc->xFinalize!=0 );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
memset(&t, 0, sizeof(t));
t.flags = MEM_Null;
t.db = pMem->db;
| > | 77735 77736 77737 77738 77739 77740 77741 77742 77743 77744 77745 77746 77747 77748 77749 |
** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
** otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
Mem t;
assert( pFunc!=0 );
assert( pMem!=0 );
assert( pFunc->xFinalize!=0 );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
memset(&t, 0, sizeof(t));
t.flags = MEM_Null;
t.db = pMem->db;
|
| ︙ | ︙ | |||
77595 77596 77597 77598 77599 77600 77601 | ** a floating-point then the value returned is the integer part. ** If pMem is a string or blob, then we make an attempt to convert ** it into an integer and return that. If pMem represents an ** an SQL-NULL value, return 0. ** ** If pMem represents a string value, its encoding might be changed. */ | | | > | 77879 77880 77881 77882 77883 77884 77885 77886 77887 77888 77889 77890 77891 77892 77893 77894 77895 77896 77897 77898 77899 77900 |
** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into an integer and return that. If pMem represents an
** an SQL-NULL value, return 0.
**
** If pMem represents a string value, its encoding might be changed.
*/
static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){
i64 value = 0;
sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
return value;
}
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){
int flags;
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
flags = pMem->flags;
if( flags & (MEM_Int|MEM_IntReal) ){
testcase( flags & MEM_IntReal );
return pMem->u.i;
}else if( flags & MEM_Real ){
|
| ︙ | ︙ | |||
77630 77631 77632 77633 77634 77635 77636 77637 77638 77639 77640 77641 77642 77643 |
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
double val = (double)0;
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
return val;
}
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
return pMem->u.r;
}else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
| > | 77915 77916 77917 77918 77919 77920 77921 77922 77923 77924 77925 77926 77927 77928 77929 |
static SQLITE_NOINLINE double memRealValue(Mem *pMem){
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
double val = (double)0;
sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
return val;
}
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
return pMem->u.r;
}else if( pMem->flags & (MEM_Int|MEM_IntReal) ){
testcase( pMem->flags & MEM_IntReal );
return (double)pMem->u.i;
|
| ︙ | ︙ | |||
77662 77663 77664 77665 77666 77667 77668 77669 77670 77671 77672 77673 77674 77675 |
/*
** The MEM structure is already a MEM_Real. Try to also make it a
** MEM_Int if we can.
*/
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
i64 ix;
assert( pMem->flags & MEM_Real );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
ix = doubleToInt64(pMem->u.r);
| > | 77948 77949 77950 77951 77952 77953 77954 77955 77956 77957 77958 77959 77960 77961 77962 |
/*
** The MEM structure is already a MEM_Real. Try to also make it a
** MEM_Int if we can.
*/
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
i64 ix;
assert( pMem!=0 );
assert( pMem->flags & MEM_Real );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
ix = doubleToInt64(pMem->u.r);
|
| ︙ | ︙ | |||
77689 77690 77691 77692 77693 77694 77695 77696 77697 77698 77699 77700 77701 77702 77703 77704 77705 77706 77707 77708 77709 77710 77711 77712 77713 77714 77715 77716 |
}
}
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
MemSetTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
}
/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
| > > | 77976 77977 77978 77979 77980 77981 77982 77983 77984 77985 77986 77987 77988 77989 77990 77991 77992 77993 77994 77995 77996 77997 77998 77999 78000 78001 78002 78003 78004 78005 |
}
}
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
MemSetTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
}
/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.r = sqlite3VdbeRealValue(pMem);
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
77736 77737 77738 77739 77740 77741 77742 77743 77744 77745 77746 77747 77748 77749 |
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number. Convert
** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
testcase( pMem->flags & MEM_Int );
testcase( pMem->flags & MEM_Real );
testcase( pMem->flags & MEM_IntReal );
testcase( pMem->flags & MEM_Null );
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){
int rc;
sqlite3_int64 ix;
| > | 78025 78026 78027 78028 78029 78030 78031 78032 78033 78034 78035 78036 78037 78038 78039 |
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number. Convert
** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
assert( pMem!=0 );
testcase( pMem->flags & MEM_Int );
testcase( pMem->flags & MEM_Real );
testcase( pMem->flags & MEM_IntReal );
testcase( pMem->flags & MEM_Null );
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null))==0 ){
int rc;
sqlite3_int64 ix;
|
| ︙ | ︙ | |||
77845 77846 77847 77848 77849 77850 77851 77852 77853 77854 77855 77856 77857 77858 77859 77860 77861 77862 77863 77864 77865 77866 77867 |
sqlite3VdbeMemSetNull((Mem*)p);
}
/*
** Delete any previous value and set the value to be a BLOB of length
** n containing all zeros.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.nZero = n;
pMem->enc = SQLITE_UTF8;
pMem->z = 0;
}
/*
** The pMem is known to contain content that needs to be destroyed prior
** to a value change. So invoke the destructor, then set the value to
** a 64-bit integer.
*/
static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
| > > > > > > > > > > > > > > > > | 78135 78136 78137 78138 78139 78140 78141 78142 78143 78144 78145 78146 78147 78148 78149 78150 78151 78152 78153 78154 78155 78156 78157 78158 78159 78160 78161 78162 78163 78164 78165 78166 78167 78168 78169 78170 78171 78172 78173 |
sqlite3VdbeMemSetNull((Mem*)p);
}
/*
** Delete any previous value and set the value to be a BLOB of length
** n containing all zeros.
*/
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.nZero = n;
pMem->enc = SQLITE_UTF8;
pMem->z = 0;
}
#else
SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
int nByte = n>0?n:1;
if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
return SQLITE_NOMEM_BKPT;
}
assert( pMem->z!=0 );
assert( sqlite3DbMallocSize(pMem->db, pMem->z)>=nByte );
memset(pMem->z, 0, nByte);
pMem->n = n>0?n:0;
pMem->flags = MEM_Blob;
pMem->enc = SQLITE_UTF8;
return SQLITE_OK;
}
#endif
/*
** The pMem is known to contain content that needs to be destroyed prior
** to a value change. So invoke the destructor, then set the value to
** a 64-bit integer.
*/
static SQLITE_NOINLINE void vdbeReleaseAndSetInt64(Mem *pMem, i64 val){
|
| ︙ | ︙ | |||
78087 78088 78089 78090 78091 78092 78093 78094 78095 78096 78097 78098 78099 78100 |
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
u16 flags = 0; /* New value for pMem->flags */
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
sqlite3VdbeMemSetNull(pMem);
return SQLITE_OK;
| > | 78393 78394 78395 78396 78397 78398 78399 78400 78401 78402 78403 78404 78405 78406 78407 |
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
u16 flags = 0; /* New value for pMem->flags */
assert( pMem!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlite3VdbeMemIsRowSet(pMem) );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
sqlite3VdbeMemSetNull(pMem);
return SQLITE_OK;
|
| ︙ | ︙ | |||
78412 78413 78414 78415 78416 78417 78418 78419 78420 78421 78422 78423 78424 78425 78426 78427 |
sqlite3_value *pVal = 0; /* New value */
int rc = SQLITE_OK; /* Return code */
ExprList *pList = 0; /* Function arguments */
int i; /* Iterator variable */
assert( pCtx!=0 );
assert( (p->flags & EP_TokenOnly)==0 );
pList = p->x.pList;
if( pList ) nVal = pList->nExpr;
pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
assert( pFunc );
if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
){
return SQLITE_OK;
}
| > > | 78719 78720 78721 78722 78723 78724 78725 78726 78727 78728 78729 78730 78731 78732 78733 78734 78735 78736 |
sqlite3_value *pVal = 0; /* New value */
int rc = SQLITE_OK; /* Return code */
ExprList *pList = 0; /* Function arguments */
int i; /* Iterator variable */
assert( pCtx!=0 );
assert( (p->flags & EP_TokenOnly)==0 );
assert( ExprUseXList(p) );
pList = p->x.pList;
if( pList ) nVal = pList->nExpr;
assert( !ExprHasProperty(p, EP_IntValue) );
pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
assert( pFunc );
if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
|| (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
){
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
78517 78518 78519 78520 78521 78522 78523 |
/* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This
** check ensures that an EP_TokenOnly expression is never passed down
** into valueFromFunction(). */
assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
if( op==TK_CAST ){
| > > | | 78826 78827 78828 78829 78830 78831 78832 78833 78834 78835 78836 78837 78838 78839 78840 78841 78842 |
/* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This
** check ensures that an EP_TokenOnly expression is never passed down
** into valueFromFunction(). */
assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
if( op==TK_CAST ){
u8 aff;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
aff = sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
testcase( rc!=SQLITE_OK );
if( *ppVal ){
sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
}
return rc;
|
| ︙ | ︙ | |||
78590 78591 78592 78593 78594 78595 78596 78597 78598 78599 78600 78601 78602 78603 78604 78605 78606 78607 78608 78609 78610 78611 78612 78613 78614 78615 78616 78617 78618 78619 78620 |
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
sqlite3VdbeMemSetNull(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
pVal = valueNew(db, pCtx);
if( !pVal ) goto no_mem;
zVal = &pExpr->u.zToken[2];
nVal = sqlite3Strlen30(zVal)-1;
assert( zVal[nVal]=='\'' );
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
0, SQLITE_DYNAMIC);
}
#endif
#ifdef SQLITE_ENABLE_STAT4
else if( op==TK_FUNCTION && pCtx!=0 ){
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
}
#endif
else if( op==TK_TRUEFALSE ){
pVal = valueNew(db, pCtx);
if( pVal ){
pVal->flags = MEM_Int;
pVal->u.i = pExpr->u.zToken[4]==0;
}
}
| > > | 78901 78902 78903 78904 78905 78906 78907 78908 78909 78910 78911 78912 78913 78914 78915 78916 78917 78918 78919 78920 78921 78922 78923 78924 78925 78926 78927 78928 78929 78930 78931 78932 78933 |
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
sqlite3VdbeMemSetNull(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
pVal = valueNew(db, pCtx);
if( !pVal ) goto no_mem;
zVal = &pExpr->u.zToken[2];
nVal = sqlite3Strlen30(zVal)-1;
assert( zVal[nVal]=='\'' );
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
0, SQLITE_DYNAMIC);
}
#endif
#ifdef SQLITE_ENABLE_STAT4
else if( op==TK_FUNCTION && pCtx!=0 ){
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
}
#endif
else if( op==TK_TRUEFALSE ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pVal = valueNew(db, pCtx);
if( pVal ){
pVal->flags = MEM_Int;
pVal->u.i = pExpr->u.zToken[4]==0;
}
}
|
| ︙ | ︙ | |||
79160 79161 79162 79163 79164 79165 79166 79167 79168 79169 79170 79171 79172 79173 79174 79175 |
i = p->nOp;
assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
p->nOp++;
pOp = &p->aOp[i];
pOp->opcode = (u8)op;
pOp->p5 = 0;
pOp->p1 = p1;
pOp->p2 = p2;
pOp->p3 = p3;
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
| > > | 79473 79474 79475 79476 79477 79478 79479 79480 79481 79482 79483 79484 79485 79486 79487 79488 79489 79490 |
i = p->nOp;
assert( p->iVdbeMagic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
assert( p->aOp!=0 );
p->nOp++;
pOp = &p->aOp[i];
assert( pOp!=0 );
pOp->opcode = (u8)op;
pOp->p5 = 0;
pOp->p1 = p1;
pOp->p2 = p2;
pOp->p3 = p3;
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
|
| ︙ | ︙ | |||
80404 80405 80406 80407 80408 80409 80410 |
sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
zOpName = sqlite3OpcodeName(pOp->opcode);
nOpName = sqlite3Strlen30(zOpName);
if( zOpName[nOpName+1] ){
int seenCom = 0;
char c;
| | | 80719 80720 80721 80722 80723 80724 80725 80726 80727 80728 80729 80730 80731 80732 80733 |
sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
zOpName = sqlite3OpcodeName(pOp->opcode);
nOpName = sqlite3Strlen30(zOpName);
if( zOpName[nOpName+1] ){
int seenCom = 0;
char c;
zSynopsis = zOpName + nOpName + 1;
if( strncmp(zSynopsis,"IF ",3)==0 ){
sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
zSynopsis = zAlt;
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
if( c=='P' ){
c = zSynopsis[++ii];
|
| ︙ | ︙ | |||
80477 80478 80479 80480 80481 80482 80483 80484 80485 80486 80487 80488 80489 80490 |
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
** that can be displayed in the P4 column of EXPLAIN output.
*/
static void displayP4Expr(StrAccum *p, Expr *pExpr){
const char *zOp = 0;
switch( pExpr->op ){
case TK_STRING:
sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
break;
case TK_INTEGER:
sqlite3_str_appendf(p, "%d", pExpr->u.iValue);
break;
case TK_NULL:
sqlite3_str_appendf(p, "NULL");
| > | 80792 80793 80794 80795 80796 80797 80798 80799 80800 80801 80802 80803 80804 80805 80806 |
** Translate the P4.pExpr value for an OP_CursorHint opcode into text
** that can be displayed in the P4 column of EXPLAIN output.
*/
static void displayP4Expr(StrAccum *p, Expr *pExpr){
const char *zOp = 0;
switch( pExpr->op ){
case TK_STRING:
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
break;
case TK_INTEGER:
sqlite3_str_appendf(p, "%d", pExpr->u.iValue);
break;
case TK_NULL:
sqlite3_str_appendf(p, "NULL");
|
| ︙ | ︙ | |||
80823 80824 80825 80826 80827 80828 80829 |
** sqlite3MemRelease() were called from here. With -O2, this jumps
** to 6.6 percent. The test case is inserting 1000 rows into a table
** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
testcase( p->flags & MEM_Agg );
testcase( p->flags & MEM_Dyn );
| < > | 81139 81140 81141 81142 81143 81144 81145 81146 81147 81148 81149 81150 81151 81152 81153 81154 |
** sqlite3MemRelease() were called from here. With -O2, this jumps
** to 6.6 percent. The test case is inserting 1000 rows into a table
** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
testcase( p->flags & MEM_Agg );
testcase( p->flags & MEM_Dyn );
if( p->flags&(MEM_Agg|MEM_Dyn) ){
testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlite3VdbeFrameMemDel );
sqlite3VdbeMemRelease(p);
}else if( p->szMalloc ){
sqlite3DbFreeNN(db, p->zMalloc);
p->szMalloc = 0;
}
p->flags = MEM_Undefined;
|
| ︙ | ︙ | |||
81972 81973 81974 81975 81976 81977 81978 |
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
/* Lock all btrees used by the statement */
sqlite3VdbeEnter(p);
/* Check for one of the special errors */
| > | | > | > > > > | 82288 82289 82290 82291 82292 82293 82294 82295 82296 82297 82298 82299 82300 82301 82302 82303 82304 82305 82306 82307 82308 82309 82310 |
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
/* Lock all btrees used by the statement */
sqlite3VdbeEnter(p);
/* Check for one of the special errors */
if( p->rc ){
mrc = p->rc & 0xff;
isSpecialError = mrc==SQLITE_NOMEM
|| mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT
|| mrc==SQLITE_FULL;
}else{
mrc = isSpecialError = 0;
}
if( isSpecialError ){
/* If the query was read-only and the error code is SQLITE_INTERRUPT,
** no rollback is necessary. Otherwise, at least a savepoint
** transaction must be rolled back to restore the database to a
** consistent state.
**
** Even if the statement is read-only, it is important to perform
|
| ︙ | ︙ | |||
82026 82027 82028 82029 82030 82031 82032 82033 82034 82035 82036 82037 82038 82039 |
rc = sqlite3VdbeCheckFk(p, 1);
if( rc!=SQLITE_OK ){
if( NEVER(p->readOnly) ){
sqlite3VdbeLeave(p);
return SQLITE_ERROR;
}
rc = SQLITE_CONSTRAINT_FOREIGNKEY;
}else{
/* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
** key constraints to hold up the transaction. This means a commit
** is required. */
rc = vdbeCommit(db, p);
}
| > > > | 82348 82349 82350 82351 82352 82353 82354 82355 82356 82357 82358 82359 82360 82361 82362 82363 82364 |
rc = sqlite3VdbeCheckFk(p, 1);
if( rc!=SQLITE_OK ){
if( NEVER(p->readOnly) ){
sqlite3VdbeLeave(p);
return SQLITE_ERROR;
}
rc = SQLITE_CONSTRAINT_FOREIGNKEY;
}else if( db->flags & SQLITE_CorruptRdOnly ){
rc = SQLITE_CORRUPT;
db->flags &= ~SQLITE_CorruptRdOnly;
}else{
/* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
** key constraints to hold up the transaction. This means a commit
** is required. */
rc = vdbeCommit(db, p);
}
|
| ︙ | ︙ | |||
84130 84131 84132 84133 84134 84135 84136 84137 84138 84139 84140 84141 84142 84143 |
if( op==SQLITE_UPDATE ){
iKey2 = v->aMem[iReg].u.i;
}else{
iKey2 = iKey1;
}
}
assert( pCsr->nField==pTab->nCol
|| (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
);
preupdate.v = v;
preupdate.pCsr = pCsr;
preupdate.op = op;
| > > | 84455 84456 84457 84458 84459 84460 84461 84462 84463 84464 84465 84466 84467 84468 84469 84470 |
if( op==SQLITE_UPDATE ){
iKey2 = v->aMem[iReg].u.i;
}else{
iKey2 = iKey1;
}
}
assert( pCsr!=0 );
assert( pCsr->eCurType==CURTYPE_BTREE );
assert( pCsr->nField==pTab->nCol
|| (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
);
preupdate.v = v;
preupdate.pCsr = pCsr;
preupdate.op = op;
|
| ︙ | ︙ | |||
84529 84530 84531 84532 84533 84534 84535 | /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify ** the function result. ** ** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the | | | | > > | > > > > > > | 84856 84857 84858 84859 84860 84861 84862 84863 84864 84865 84866 84867 84868 84869 84870 84871 84872 84873 84874 84875 84876 84877 84878 84879 84880 84881 84882 84883 84884 84885 84886 84887 84888 84889 84890 84891 84892 |
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
** the function result.
**
** The setStrOrError() function calls sqlite3VdbeMemSetStr() to store the
** result as a string or blob. Appropriate errors are set if the string/blob
** is too big or if an OOM occurs.
**
** The invokeValueDestructor(P,X) routine invokes destructor function X()
** on value P is not going to be used and need to be destroyed.
*/
static void setResultStrOrError(
sqlite3_context *pCtx, /* Function context */
const char *z, /* String pointer */
int n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
int rc = sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel);
if( rc ){
if( rc==SQLITE_TOOBIG ){
sqlite3_result_error_toobig(pCtx);
}else{
/* The only errors possible from sqlite3VdbeMemSetStr are
** SQLITE_TOOBIG and SQLITE_NOMEM */
assert( rc==SQLITE_NOMEM );
sqlite3_result_error_nomem(pCtx);
}
}
}
static int invokeValueDestructor(
const void *p, /* Value to destroy */
void (*xDel)(void*), /* The destructor */
sqlite3_context *pCtx /* Set a SQLITE_TOOBIG error if no NULL */
){
|
| ︙ | ︙ | |||
84700 84701 84702 84703 84704 84705 84706 84707 84708 84709 84710 84711 84712 84713 84714 84715 |
}
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
return SQLITE_TOOBIG;
}
sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
return SQLITE_OK;
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
| > > > > | 85035 85036 85037 85038 85039 85040 85041 85042 85043 85044 85045 85046 85047 85048 85049 85050 85051 85052 85053 85054 |
}
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
return SQLITE_TOOBIG;
}
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
return SQLITE_OK;
#else
return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
#endif
}
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
|
| ︙ | ︙ | |||
85713 85714 85715 85716 85717 85718 85719 85720 85721 85722 85723 85724 85725 85726 85727 |
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
| > > > > | 86052 86053 86054 86055 86056 86057 86058 86059 86060 86061 86062 86063 86064 86065 86066 86067 86068 86069 86070 |
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#endif
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
|
| ︙ | ︙ | |||
86001 86002 86003 86004 86005 86006 86007 86008 86009 86010 86011 86012 86013 86014 |
}
/* If the old.* record has not yet been loaded into memory, do so now. */
if( p->pUnpacked==0 ){
u32 nRec;
u8 *aRec;
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
aRec = sqlite3DbMallocRaw(db, nRec);
if( !aRec ) goto preupdate_old_out;
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
if( rc==SQLITE_OK ){
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
| > | 86344 86345 86346 86347 86348 86349 86350 86351 86352 86353 86354 86355 86356 86357 86358 |
}
/* If the old.* record has not yet been loaded into memory, do so now. */
if( p->pUnpacked==0 ){
u32 nRec;
u8 *aRec;
assert( p->pCsr->eCurType==CURTYPE_BTREE );
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
aRec = sqlite3DbMallocRaw(db, nRec);
if( !aRec ) goto preupdate_old_out;
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
if( rc==SQLITE_OK ){
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
|
| ︙ | ︙ | |||
87089 87090 87091 87092 87093 87094 87095 87096 87097 87098 87099 87100 87101 87102 |
if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
return out2PrereleaseWithClear(pOut);
}else{
pOut->flags = MEM_Int;
return pOut;
}
}
/*
** Return the symbolic name for the data type of a pMem
*/
static const char *vdbeMemTypeName(Mem *pMem){
static const char *azTypes[] = {
/* SQLITE_INTEGER */ "INT",
| > > > > > > > > > > > > > > > > > > > > > > > > > | 87433 87434 87435 87436 87437 87438 87439 87440 87441 87442 87443 87444 87445 87446 87447 87448 87449 87450 87451 87452 87453 87454 87455 87456 87457 87458 87459 87460 87461 87462 87463 87464 87465 87466 87467 87468 87469 87470 87471 |
if( VdbeMemDynamic(pOut) ){ /*OPTIMIZATION-IF-FALSE*/
return out2PrereleaseWithClear(pOut);
}else{
pOut->flags = MEM_Int;
return pOut;
}
}
/*
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
** with pOp->p3. Return the hash.
*/
static u64 filterHash(const Mem *aMem, const Op *pOp){
int i, mx;
u64 h = 0;
i = pOp->p3;
assert( pOp->p4type==P4_INT32 );
mx = i + pOp->p4.i;
for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){
const Mem *p = &aMem[i];
if( p->flags & (MEM_Int|MEM_IntReal) ){
h += p->u.i;
}else if( p->flags & MEM_Real ){
h += sqlite3VdbeIntValue(p);
}else if( p->flags & (MEM_Str|MEM_Blob) ){
h += p->n;
if( p->flags & MEM_Zero ) h += p->u.nZero;
}
}
return h;
}
/*
** Return the symbolic name for the data type of a pMem
*/
static const char *vdbeMemTypeName(Mem *pMem){
static const char *azTypes[] = {
/* SQLITE_INTEGER */ "INT",
|
| ︙ | ︙ | |||
87744 87745 87746 87747 87748 87749 87750 | break; } /* Opcode: Blob P1 P2 * P4 * ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this | | > > > > > | > | 88113 88114 88115 88116 88117 88118 88119 88120 88121 88122 88123 88124 88125 88126 88127 88128 88129 88130 88131 88132 88133 88134 88135 88136 88137 88138 |
break;
}
/* Opcode: Blob P1 P2 * P4 *
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
** blob in register P2. If P4 is a NULL pointer, then construct
** a zero-filled blob that is P1 bytes long in P2.
*/
case OP_Blob: { /* out2 */
assert( pOp->p1 <= SQLITE_MAX_LENGTH );
pOut = out2Prerelease(p, pOp);
if( pOp->p4.z==0 ){
sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1);
if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem;
}else{
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
}
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: Variable P1 P2 * P4 *
** Synopsis: r[P2]=parameter(P1,P4)
|
| ︙ | ︙ | |||
87898 87899 87900 87901 87902 87903 87904 | pIn1 = &aMem[pOp->p1]; assert( (pIn1->flags & MEM_Int)!=0 ); pOut = &aMem[pOp->p2]; sqlite3VdbeMemSetInt64(pOut, pIn1->u.i); break; } | | < < | | > > | | | | < < | | 88273 88274 88275 88276 88277 88278 88279 88280 88281 88282 88283 88284 88285 88286 88287 88288 88289 88290 88291 88292 88293 88294 88295 88296 88297 88298 88299 88300 88301 88302 |
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Int)!=0 );
pOut = &aMem[pOp->p2];
sqlite3VdbeMemSetInt64(pOut, pIn1->u.i);
break;
}
/* Opcode: FkCheck * * * * *
**
** Halt with an SQLITE_CONSTRAINT error if there are any unresolved
** foreign key constraint violations. If there are no foreign key
** constraint violations, this is a no-op.
**
** FK constraint violations are also checked when the prepared statement
** exits. This opcode is used to raise foreign key constraint errors prior
** to returning results such as a row change count or the result of a
** RETURNING clause.
*/
case OP_FkCheck: {
if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
goto abort_due_to_error;
}
break;
}
/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
|
| ︙ | ︙ | |||
89318 89319 89320 89321 89322 89323 89324 |
break;
}else{
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
| | > > > > > | 89691 89692 89693 89694 89695 89696 89697 89698 89699 89700 89701 89702 89703 89704 89705 89706 89707 89708 89709 89710 89711 89712 89713 89714 89715 89716 89717 89718 89719 |
break;
}else{
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
/* Opcode: TypeCheck P1 P2 P3 P4 *
** Synopsis: typecheck(r[P1@P2])
**
** Apply affinities to the range of P2 registers beginning with P1.
** Take the affinities from the Table object in P4. If any value
** cannot be coerced into the correct type, then raise an error.
**
** This opcode is similar to OP_Affinity except that this opcode
** forces the register type to the Table column type. This is used
** to implement "strict affinity".
**
** GENERATED ALWAYS AS ... STATIC columns are only checked if P3
** is zero. When P3 is non-zero, no type checking occurs for
** static generated columns. Virtual columns are computed at query time
** and so they are never checked.
**
** Preconditions:
**
** <ul>
** <li> P2 should be the number of non-virtual columns in the
** table of P4.
** <li> Table P4 should be a STRICT table.
|
| ︙ | ︙ | |||
89351 89352 89353 89354 89355 89356 89357 |
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
assert( pTab->nNVCol==pOp->p2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
for(i=0; i<pTab->nCol; i++){
| > | > > | 89729 89730 89731 89732 89733 89734 89735 89736 89737 89738 89739 89740 89741 89742 89743 89744 89745 89746 |
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
assert( pTab->nNVCol==pOp->p2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
for(i=0; i<pTab->nCol; i++){
if( aCol[i].colFlags & COLFLAG_GENERATED ){
if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
if( pOp->p3 ){ pIn1++; continue; }
}
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
applyAffinity(pIn1, aCol[i].affinity, encoding);
if( (pIn1->flags & MEM_Null)==0 ){
switch( aCol[i].eCType ){
case COLTYPE_BLOB: {
if( (pIn1->flags & MEM_Blob)==0 ) goto vdbe_type_error;
break;
|
| ︙ | ︙ | |||
89754 89755 89756 89757 89758 89759 89760 | assert( nByte==(int)(zPayload - (u8*)pOut->z) ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); REGISTER_TRACE(pOp->p3, pOut); break; } | | | 90135 90136 90137 90138 90139 90140 90141 90142 90143 90144 90145 90146 90147 90148 90149 | assert( nByte==(int)(zPayload - (u8*)pOut->z) ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); REGISTER_TRACE(pOp->p3, pOut); break; } /* Opcode: Count P1 P2 P3 * * ** Synopsis: r[P2]=count() ** ** Store the number of entries (an integer value) in the table or index ** opened by cursor P1 in register P2. ** ** If P3==0, then an exact count is obtained, which involves visiting ** every btree page of the table. But if P3 is non-zero, an estimate |
| ︙ | ︙ | |||
90075 90076 90077 90078 90079 90080 90081 | int iMeta = 0; assert( p->bIsReader ); assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p2>=0 && pOp->p2<=2 ); assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); | > | > > | > > > > > | 90456 90457 90458 90459 90460 90461 90462 90463 90464 90465 90466 90467 90468 90469 90470 90471 90472 90473 90474 90475 90476 90477 90478 90479 |
int iMeta = 0;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( rc==SQLITE_OK );
if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){
if( db->flags & SQLITE_QueryOnly ){
/* Writes prohibited by the "PRAGMA query_only=TRUE" statement */
rc = SQLITE_READONLY;
}else{
/* Writes prohibited due to a prior SQLITE_CORRUPT in the current
** transaction */
rc = SQLITE_CORRUPT;
}
goto abort_due_to_error;
}
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
testcase( rc==SQLITE_BUSY_SNAPSHOT );
|
| ︙ | ︙ | |||
90118 90119 90120 90121 90122 90123 90124 |
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
| > | | 90507 90508 90509 90510 90511 90512 90513 90514 90515 90516 90517 90518 90519 90520 90521 90522 |
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( rc==SQLITE_OK
&& pOp->p5
&& (iMeta!=pOp->p3
|| db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
|
| ︙ | ︙ | |||
90512 90513 90514 90515 90516 90517 90518 |
assert( pOp->p2==0 ); /* Only used when number of columns is zero */
assert( pOp->opcode==OP_OpenEphemeral );
assert( aMem[pOp->p3].flags & MEM_Null );
aMem[pOp->p3].n = 0;
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
| | | 90902 90903 90904 90905 90906 90907 90908 90909 90910 90911 90912 90913 90914 90915 90916 |
assert( pOp->p2==0 ); /* Only used when number of columns is zero */
assert( pOp->opcode==OP_OpenEphemeral );
assert( aMem[pOp->p3].flags & MEM_Null );
aMem[pOp->p3].n = 0;
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
if( pCx && !pCx->hasBeenDuped && ALWAYS(pOp->p2<=pCx->nField) ){
/* If the ephermeral table is already open and has no duplicates from
** OP_OpenDup, then erase all existing content so that the table is
** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
|
| ︙ | ︙ | |||
91675 91676 91677 91678 91679 91680 91681 |
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
}else{
pTab = 0;
| | | 92065 92066 92067 92068 92069 92070 92071 92072 92073 92074 92075 92076 92077 92078 92079 |
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
}else{
pTab = 0;
zDb = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
|
| ︙ | ︙ | |||
91828 91829 91830 91831 91832 91833 91834 |
assert( pOp->p4.pTab!=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
}else{
| | | > | | 92218 92219 92220 92221 92222 92223 92224 92225 92226 92227 92228 92229 92230 92231 92232 92233 92234 92235 92236 92237 92238 92239 |
assert( pOp->p4.pTab!=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){
pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
}else{
zDb = 0;
pTab = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
assert( db->xPreUpdateCallback==0 || pTab==pOp->p4.pTab );
if( db->xPreUpdateCallback && pTab ){
assert( !(opflags & OPFLAG_ISUPDATE)
|| HasRowid(pTab)==0
|| (aMem[pOp->p3].flags & MEM_Int)
);
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
|
| ︙ | ︙ | |||
91875 91876 91877 91878 91879 91880 91881 |
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
if( opflags & OPFLAG_NCHANGE ){
p->nChange++;
| | | 92266 92267 92268 92269 92270 92271 92272 92273 92274 92275 92276 92277 92278 92279 92280 |
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
if( opflags & OPFLAG_NCHANGE ){
p->nChange++;
if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
pC->movetoTarget);
assert( pC->iDb>=0 );
}
}
break;
|
| ︙ | ︙ | |||
92923 92924 92925 92926 92927 92928 92929 |
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
p->expired = 0;
}else
#endif
{
| | | 93314 93315 93316 93317 93318 93319 93320 93321 93322 93323 93324 93325 93326 93327 93328 |
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
p->expired = 0;
}else
#endif
{
zSchema = LEGACY_SCHEMA_TABLE;
initData.db = db;
initData.iDb = iDb;
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
initData.mxPage = sqlite3BtreeLastPage(db->aDb[iDb].pBt);
zSql = sqlite3MPrintf(db,
"SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
|
| ︙ | ︙ | |||
94143 94144 94145 94146 94147 94148 94149 94150 94151 94152 94153 94154 94155 94156 | Mem **apArg; pQuery = &aMem[pOp->p3]; pArgc = &pQuery[1]; pCur = p->apCsr[pOp->p1]; assert( memIsValid(pQuery) ); REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->eCurType==CURTYPE_VTAB ); pVCur = pCur->uc.pVCur; pVtab = pVCur->pVtab; pModule = pVtab->pModule; /* Grab the index number and argc parameters */ assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); | > | 94534 94535 94536 94537 94538 94539 94540 94541 94542 94543 94544 94545 94546 94547 94548 | Mem **apArg; pQuery = &aMem[pOp->p3]; pArgc = &pQuery[1]; pCur = p->apCsr[pOp->p1]; assert( memIsValid(pQuery) ); REGISTER_TRACE(pOp->p3, pQuery); assert( pCur!=0 ); assert( pCur->eCurType==CURTYPE_VTAB ); pVCur = pCur->uc.pVCur; pVtab = pVCur->pVtab; pModule = pVtab->pModule; /* Grab the index number and argc parameters */ assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); |
| ︙ | ︙ | |||
94191 94192 94193 94194 94195 94196 94197 94198 94199 94200 94201 94202 94203 94204 |
case OP_VColumn: {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->eCurType==CURTYPE_VTAB );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
| > | 94583 94584 94585 94586 94587 94588 94589 94590 94591 94592 94593 94594 94595 94596 94597 |
case OP_VColumn: {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
|
| ︙ | ︙ | |||
94244 94245 94246 94247 94248 94249 94250 94251 94252 94253 94254 94255 94256 94257 |
case OP_VNext: { /* jump */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
pCur = p->apCsr[pOp->p1];
assert( pCur->eCurType==CURTYPE_VTAB );
if( pCur->nullRow ){
break;
}
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xNext );
| > | 94637 94638 94639 94640 94641 94642 94643 94644 94645 94646 94647 94648 94649 94650 94651 |
case OP_VNext: { /* jump */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
pCur = p->apCsr[pOp->p1];
assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
if( pCur->nullRow ){
break;
}
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xNext );
|
| ︙ | ︙ | |||
94339 94340 94341 94342 94343 94344 94345 |
** apply in the case of a constraint failure on an insert or update.
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int nArg;
int i;
| | | 94733 94734 94735 94736 94737 94738 94739 94740 94741 94742 94743 94744 94745 94746 94747 |
** apply in the case of a constraint failure on an insert or update.
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int nArg;
int i;
sqlite_int64 rowid = 0;
Mem **apArg;
Mem *pX;
assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
assert( p->readOnly==0 );
|
| ︙ | ︙ | |||
94526 94527 94528 94529 94530 94531 94532 94533 94534 94535 94536 94537 94538 94539 |
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
}
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: Trace P1 P2 * P4 *
**
** Write P4 on the statement trace output if statement tracing is
** enabled.
**
** Operand P1 must be 0x7fffffff and P2 must positive.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 94920 94921 94922 94923 94924 94925 94926 94927 94928 94929 94930 94931 94932 94933 94934 94935 94936 94937 94938 94939 94940 94941 94942 94943 94944 94945 94946 94947 94948 94949 94950 94951 94952 94953 94954 94955 94956 94957 94958 94959 94960 94961 94962 94963 94964 94965 94966 94967 94968 94969 94970 94971 94972 94973 94974 94975 94976 94977 94978 94979 94980 94981 94982 94983 94984 94985 94986 94987 94988 94989 94990 94991 94992 94993 94994 94995 94996 94997 94998 94999 95000 95001 95002 95003 95004 |
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
}
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: FilterAdd P1 * P3 P4 *
** Synopsis: filter(P1) += key(P3@P4)
**
** Compute a hash on the P4 registers starting with r[P3] and
** add that hash to the bloom filter contained in r[P1].
*/
case OP_FilterAdd: {
u64 h;
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags & MEM_Blob );
assert( pIn1->n>0 );
h = filterHash(aMem, pOp);
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
int ii;
for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
registerTrace(ii, &aMem[ii]);
}
printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
}
#endif
h %= pIn1->n;
pIn1->z[h/8] |= 1<<(h&7);
break;
}
/* Opcode: Filter P1 P2 P3 P4 *
** Synopsis: if key(P3@P4) not in filter(P1) goto P2
**
** Compute a hash on the key contained in the P4 registers starting
** with r[P3]. Check to see if that hash is found in the
** bloom filter hosted by register P1. If it is not present then
** maybe jump to P2. Otherwise fall through.
**
** False negatives are harmless. It is always safe to fall through,
** even if the value is in the bloom filter. A false negative causes
** more CPU cycles to be used, but it should still yield the correct
** answer. However, an incorrect answer may well arise from a
** false positive - if the jump is taken when it should fall through.
*/
case OP_Filter: { /* jump */
u64 h;
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Blob)!=0 );
assert( pIn1->n >= 1 );
h = filterHash(aMem, pOp);
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
int ii;
for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
registerTrace(ii, &aMem[ii]);
}
printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
}
#endif
h %= pIn1->n;
if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){
VdbeBranchTaken(1, 2);
p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++;
goto jump_to_p2;
}else{
p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++;
VdbeBranchTaken(0, 2);
}
break;
}
/* Opcode: Trace P1 P2 * P4 *
**
** Write P4 on the statement trace output if statement tracing is
** enabled.
**
** Operand P1 must be 0x7fffffff and P2 must positive.
|
| ︙ | ︙ | |||
94786 94787 94788 94789 94790 94791 94792 |
rc = SQLITE_NOMEM_BKPT;
}else if( rc==SQLITE_IOERR_CORRUPTFS ){
rc = SQLITE_CORRUPT_BKPT;
}
assert( rc );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
| > > > > > > > | > > > | 95251 95252 95253 95254 95255 95256 95257 95258 95259 95260 95261 95262 95263 95264 95265 95266 95267 95268 95269 95270 95271 95272 95273 95274 95275 95276 95277 95278 95279 95280 95281 95282 95283 95284 95285 95286 95287 |
rc = SQLITE_NOMEM_BKPT;
}else if( rc==SQLITE_IOERR_CORRUPTFS ){
rc = SQLITE_CORRUPT_BKPT;
}
assert( rc );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
const char *zTrace = p->zSql;
if( zTrace==0 ){
if( aOp[0].opcode==OP_Trace ){
zTrace = aOp[0].p4.z;
}
if( zTrace==0 ) zTrace = "???";
}
printf("ABORT-due-to-error (rc=%d): %s\n", rc, zTrace);
}
#endif
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
}
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
db->flags |= SQLITE_CorruptRdOnly;
}
rc = SQLITE_ERROR;
if( resetSchemaOnFault>0 ){
sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
}
/* This is the only way out of this procedure. We have to
** release the mutexes on btrees that were acquired at the
|
| ︙ | ︙ | |||
94930 94931 94932 94933 94934 94935 94936 |
assert( v->aOp[v->pc].opcode==OP_NotExists );
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
}
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
| > > > | | 95405 95406 95407 95408 95409 95410 95411 95412 95413 95414 95415 95416 95417 95418 95419 95420 95421 95422 |
assert( v->aOp[v->pc].opcode==OP_NotExists );
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
}
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
u32 type;
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
testcase( pC->nHdrParsed==p->iCol );
testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
);
rc = SQLITE_ERROR;
|
| ︙ | ︙ | |||
95067 95068 95069 95070 95071 95072 95073 |
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( db->flags&SQLITE_ForeignKeys ){
/* Check that the column is not part of an FK child key definition. It
** is not necessary to check if it is part of a parent key, as parent
** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
| | | 95545 95546 95547 95548 95549 95550 95551 95552 95553 95554 95555 95556 95557 95558 95559 |
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( db->flags&SQLITE_ForeignKeys ){
/* Check that the column is not part of an FK child key definition. It
** is not necessary to check if it is part of a parent key, as parent
** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
assert( IsOrdinaryTable(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
int j;
for(j=0; j<pFKey->nCol; j++){
if( pFKey->aCol[j].iFrom==iCol ){
zFault = "foreign key";
}
}
|
| ︙ | ︙ | |||
95275 95276 95277 95278 95279 95280 95281 95282 95283 95284 95285 95286 95287 95288 |
** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
** slightly more efficient). Since you cannot write to a PK column
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
sqlite3_int64 iKey;
iKey = sqlite3BtreeIntegerKey(p->pCsr);
sqlite3VdbePreUpdateHook(
v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
#endif
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
| > > | 95753 95754 95755 95756 95757 95758 95759 95760 95761 95762 95763 95764 95765 95766 95767 95768 |
** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually
** slightly more efficient). Since you cannot write to a PK column
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
sqlite3_int64 iKey;
iKey = sqlite3BtreeIntegerKey(p->pCsr);
assert( v->apCsr[0]!=0 );
assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
sqlite3VdbePreUpdateHook(
v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
#endif
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
|
| ︙ | ︙ | |||
96657 96658 96659 96660 96661 96662 96663 |
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
void *p = 0;
int chunksize = 4*1024;
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
| | | 97137 97138 97139 97140 97141 97142 97143 97144 97145 97146 97147 97148 97149 97150 97151 |
static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){
void *p = 0;
int chunksize = 4*1024;
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
if( p ) sqlite3OsUnfetch(pFd, 0, p);
}
}
#else
# define vdbeSorterExtendFile(x,y,z)
#endif
/*
|
| ︙ | ︙ | |||
97375 97376 97377 97378 97379 97380 97381 97382 97383 97384 97385 97386 97387 97388 |
pIncr->pTask = pTask;
pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2);
pTask->file2.iEof += pIncr->mxSz;
}else{
vdbeMergeEngineFree(pMerger);
rc = SQLITE_NOMEM_BKPT;
}
return rc;
}
#if SQLITE_MAX_WORKER_THREADS>0
/*
** Set the "use-threads" flag on object pIncr.
*/
| > | 97855 97856 97857 97858 97859 97860 97861 97862 97863 97864 97865 97866 97867 97868 97869 |
pIncr->pTask = pTask;
pIncr->mxSz = MAX(pTask->pSorter->mxKeysize+9,pTask->pSorter->mxPmaSize/2);
pTask->file2.iEof += pIncr->mxSz;
}else{
vdbeMergeEngineFree(pMerger);
rc = SQLITE_NOMEM_BKPT;
}
assert( *ppOut!=0 || rc!=SQLITE_OK );
return rc;
}
#if SQLITE_MAX_WORKER_THREADS>0
/*
** Set the "use-threads" flag on object pIncr.
*/
|
| ︙ | ︙ | |||
99076 99077 99078 99079 99080 99081 99082 |
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( pExpr->pRight ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
pExpr = pExpr->pRight;
continue;
| | | 99557 99558 99559 99560 99561 99562 99563 99564 99565 99566 99567 99568 99569 99570 99571 |
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( pExpr->pRight ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
pExpr = pExpr->pRight;
continue;
}else if( ExprUseXSelect(pExpr) ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
}else{
if( pExpr->x.pList ){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
|
| ︙ | ︙ | |||
99348 99349 99350 99351 99352 99353 99354 99355 99356 99357 99358 99359 99360 99361 |
pDup = sqlite3ExprDup(db, pOrig, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDup);
pDup = 0;
}else{
incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
** The pExpr->u.zToken might point into memory that will be freed by the
| > | 99829 99830 99831 99832 99833 99834 99835 99836 99837 99838 99839 99840 99841 99842 99843 |
pDup = sqlite3ExprDup(db, pOrig, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDup);
pDup = 0;
}else{
incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
** The pExpr->u.zToken might point into memory that will be freed by the
|
| ︙ | ︙ | |||
99451 99452 99453 99454 99455 99456 99457 99458 99459 99460 99461 99462 99463 99464 |
** return the appropriate colUsed mask.
*/
SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){
int n;
Table *pExTab;
n = pExpr->iColumn;
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
testcase( pExTab->nCol==BMS-1 );
testcase( pExTab->nCol==BMS );
| > | 99933 99934 99935 99936 99937 99938 99939 99940 99941 99942 99943 99944 99945 99946 99947 |
** return the appropriate colUsed mask.
*/
SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){
int n;
Table *pExTab;
n = pExpr->iColumn;
assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
&& (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
){
testcase( pExTab->nCol==BMS-1 );
testcase( pExTab->nCol==BMS );
|
| ︙ | ︙ | |||
99588 99589 99590 99591 99592 99593 99594 99595 99596 99597 99598 99599 99600 99601 |
}
if( zTab ){
const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
assert( zTabName!=0 );
if( sqlite3StrICmp(zTabName, zTab)!=0 ){
continue;
}
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
hCol = sqlite3StrIHash(zCol);
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
if( pCol->hName==hCol
| > | 100071 100072 100073 100074 100075 100076 100077 100078 100079 100080 100081 100082 100083 100084 100085 |
}
if( zTab ){
const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
assert( zTabName!=0 );
if( sqlite3StrICmp(zTabName, zTab)!=0 ){
continue;
}
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
hCol = sqlite3StrIHash(zCol);
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
if( pCol->hName==hCol
|
| ︙ | ︙ | |||
99619 99620 99621 99622 99623 99624 99625 99626 99627 99628 99629 99630 99631 99632 |
if( 0==cnt && VisibleRowid(pTab) ){
cntTab++;
pMatch = pItem;
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->y.pTab = pMatch->pTab;
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->y.pTab->pSchema;
| > | 100103 100104 100105 100106 100107 100108 100109 100110 100111 100112 100113 100114 100115 100116 100117 |
if( 0==cnt && VisibleRowid(pTab) ){
cntTab++;
pMatch = pItem;
}
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pMatch->pTab;
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->y.pTab->pSchema;
|
| ︙ | ︙ | |||
99692 99693 99694 99695 99696 99697 99698 99699 99700 99701 99702 99703 99704 99705 99706 99707 99708 99709 99710 99711 99712 99713 99714 99715 99716 99717 |
}
if( iCol<pTab->nCol ){
cnt++;
pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
}
}else
#endif /* SQLITE_OMIT_UPSERT */
{
pExpr->y.pTab = pTab;
if( pParse->bReturning ){
eNewExprOp = TK_REGISTER;
pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
sqlite3TableColumnToStorage(pTab, iCol) + 1;
}else{
pExpr->iColumn = (i16)iCol;
| > > | 100177 100178 100179 100180 100181 100182 100183 100184 100185 100186 100187 100188 100189 100190 100191 100192 100193 100194 100195 100196 100197 100198 100199 100200 100201 100202 100203 100204 |
}
if( iCol<pTab->nCol ){
cnt++;
pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
}
}else
#endif /* SQLITE_OMIT_UPSERT */
{
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pTab;
if( pParse->bReturning ){
eNewExprOp = TK_REGISTER;
pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
sqlite3TableColumnToStorage(pTab, iCol) + 1;
}else{
pExpr->iColumn = (i16)iCol;
|
| ︙ | ︙ | |||
99778 99779 99780 99781 99782 99783 99784 |
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
if( pEList->a[j].eEName==ENAME_NAME
&& sqlite3_stricmp(zAs, zCol)==0
){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
| | | | 100265 100266 100267 100268 100269 100270 100271 100272 100273 100274 100275 100276 100277 100278 100279 100280 |
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
if( pEList->a[j].eEName==ENAME_NAME
&& sqlite3_stricmp(zAs, zCol)==0
){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 );
assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
return WRC_Abort;
}
if( ExprHasProperty(pOrig, EP_Win)
&& ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC )
|
| ︙ | ︙ | |||
99851 99852 99853 99854 99855 99856 99857 |
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
pExpr->op = TK_STRING;
| | | 100338 100339 100340 100341 100342 100343 100344 100345 100346 100347 100348 100349 100350 100351 100352 |
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
pExpr->op = TK_STRING;
memset(&pExpr->y, 0, sizeof(pExpr->y));
return WRC_Prune;
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
return WRC_Prune;
}
}
|
| ︙ | ︙ | |||
99937 99938 99939 99940 99941 99942 99943 |
** Allocate and return a pointer to an expression to load the column iCol
** from datasource iSrc in SrcList pSrc.
*/
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
SrcItem *pItem = &pSrc->a[iSrc];
| > > | | 100424 100425 100426 100427 100428 100429 100430 100431 100432 100433 100434 100435 100436 100437 100438 100439 100440 |
** Allocate and return a pointer to an expression to load the column iCol
** from datasource iSrc in SrcList pSrc.
*/
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab;
assert( ExprUseYTab(p) );
pTab = p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
if( (pTab->tabFlags & TF_HasGenerated)!=0
&& (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0
|
| ︙ | ︙ | |||
100004 100005 100006 100007 100008 100009 100010 100011 100012 100013 100014 100015 100016 100017 |
** Expression p should encode a floating point value between 1.0 and 0.0.
** Return 1024 times this value. Or return -1 if p is not a floating point
** value between 1.0 and 0.0.
*/
static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*134217728.0);
}
/*
| > | 100493 100494 100495 100496 100497 100498 100499 100500 100501 100502 100503 100504 100505 100506 100507 |
** Expression p should encode a floating point value between 1.0 and 0.0.
** Return 1024 times this value. Or return -1 if p is not a floating point
** value between 1.0 and 0.0.
*/
static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
assert( !ExprHasProperty(p, EP_IntValue) );
sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
assert( r>=0.0 );
if( r>1.0 ) return -1;
return (int)(r*134217728.0);
}
/*
|
| ︙ | ︙ | |||
100052 100053 100054 100055 100056 100057 100058 100059 100060 100061 100062 100063 100064 100065 |
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
SrcItem *pItem;
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
break;
}
| > | 100542 100543 100544 100545 100546 100547 100548 100549 100550 100551 100552 100553 100554 100555 100556 |
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
SrcItem *pItem;
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
break;
}
|
| ︙ | ︙ | |||
100084 100085 100086 100087 100088 100089 100090 100091 100092 100093 100094 100095 100096 100097 |
int i;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
testcase( ExprHasProperty(pExpr, EP_FromJoin) );
if( pExpr->op==TK_NOTNULL ){
pExpr->u.zToken = "true";
ExprSetProperty(pExpr, EP_IsTrue);
}else{
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
}
| > | 100575 100576 100577 100578 100579 100580 100581 100582 100583 100584 100585 100586 100587 100588 100589 |
int i;
for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
anRef[i] = p->nRef;
}
sqlite3WalkExpr(pWalker, pExpr->pLeft);
if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
testcase( ExprHasProperty(pExpr, EP_FromJoin) );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->op==TK_NOTNULL ){
pExpr->u.zToken = "true";
ExprSetProperty(pExpr, EP_IsTrue);
}else{
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
}
|
| ︙ | ︙ | |||
100119 100120 100121 100122 100123 100124 100125 100126 100127 100128 100129 100130 100131 100132 100133 100134 100135 100136 100137 100138 100139 100140 100141 100142 100143 100144 100145 100146 100147 100148 100149 100150 |
const char *zTable;
const char *zDb;
Expr *pRight;
if( pExpr->op==TK_ID ){
zDb = 0;
zTable = 0;
zColumn = pExpr->u.zToken;
}else{
Expr *pLeft = pExpr->pLeft;
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
NC_IdxExpr|NC_GenCol, 0);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
}else{
assert( pRight->op==TK_DOT );
zDb = pLeft->u.zToken;
pLeft = pRight->pLeft;
pRight = pRight->pRight;
}
zTable = pLeft->u.zToken;
zColumn = pRight->u.zToken;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
| > > > > | 100611 100612 100613 100614 100615 100616 100617 100618 100619 100620 100621 100622 100623 100624 100625 100626 100627 100628 100629 100630 100631 100632 100633 100634 100635 100636 100637 100638 100639 100640 100641 100642 100643 100644 100645 100646 |
const char *zTable;
const char *zDb;
Expr *pRight;
if( pExpr->op==TK_ID ){
zDb = 0;
zTable = 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
zColumn = pExpr->u.zToken;
}else{
Expr *pLeft = pExpr->pLeft;
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
NC_IdxExpr|NC_GenCol, 0);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
}else{
assert( pRight->op==TK_DOT );
assert( !ExprHasProperty(pRight, EP_IntValue) );
zDb = pLeft->u.zToken;
pLeft = pRight->pLeft;
pRight = pRight->pRight;
}
assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) );
zTable = pLeft->u.zToken;
zColumn = pRight->u.zToken;
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
|
| ︙ | ︙ | |||
100161 100162 100163 100164 100165 100166 100167 |
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
#endif
| | | 100657 100658 100659 100660 100661 100662 100663 100664 100665 100666 100667 100668 100669 100670 100671 |
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
#endif
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){
pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
if( pDef==0 ){
no_such_func = 1;
|
| ︙ | ︙ | |||
100325 100326 100327 100328 100329 100330 100331 |
}
#endif
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
Select *pSel = pNC->pWinSelect;
| | | > | > > | 100821 100822 100823 100824 100825 100826 100827 100828 100829 100830 100831 100832 100833 100834 100835 100836 100837 100838 100839 100840 100841 100842 100843 100844 100845 100846 100847 100848 100849 100850 100851 100852 100853 100854 100855 100856 100857 100858 100859 |
}
#endif
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
Select *pSel = pNC->pWinSelect;
assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
if( pParse->db->mallocFailed ) break;
}
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pWin->pFilter);
sqlite3WindowLink(pSel, pWin);
pNC->ncFlags |= NC_HasWin;
}else
#endif /* SQLITE_OMIT_WINDOWFUNC */
{
NameContext *pNC2; /* For looping up thru outer contexts */
pExpr->op = TK_AGG_FUNCTION;
pExpr->op2 = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
}
#endif
pNC2 = pNC;
while( pNC2
&& sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
){
pExpr->op2++;
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
|
| ︙ | ︙ | |||
100374 100375 100376 100377 100378 100379 100380 |
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
#endif
case TK_IN: {
testcase( pExpr->op==TK_IN );
| | | 100873 100874 100875 100876 100877 100878 100879 100880 100881 100882 100883 100884 100885 100886 100887 |
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
#endif
case TK_IN: {
testcase( pExpr->op==TK_IN );
if( ExprUseXSelect(pExpr) ){
int nRef = pNC->nRef;
testcase( pNC->ncFlags & NC_IsCheck );
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
if( pNC->ncFlags & NC_SelfRef ){
notValidImpl(pParse, pNC, "subqueries", pExpr);
|
| ︙ | ︙ | |||
100431 100432 100433 100434 100435 100436 100437 100438 100439 100440 100441 100442 100443 100444 |
case TK_GT:
case TK_GE: {
int nLeft, nRight;
if( pParse->db->mallocFailed ) break;
assert( pExpr->pLeft!=0 );
nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
if( pExpr->op==TK_BETWEEN ){
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
if( nRight==nLeft ){
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
}
}else{
assert( pExpr->pRight!=0 );
nRight = sqlite3ExprVectorSize(pExpr->pRight);
| > | 100930 100931 100932 100933 100934 100935 100936 100937 100938 100939 100940 100941 100942 100943 100944 |
case TK_GT:
case TK_GE: {
int nLeft, nRight;
if( pParse->db->mallocFailed ) break;
assert( pExpr->pLeft!=0 );
nLeft = sqlite3ExprVectorSize(pExpr->pLeft);
if( pExpr->op==TK_BETWEEN ){
assert( ExprUseXList(pExpr) );
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
if( nRight==nLeft ){
nRight = sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
}
}else{
assert( pExpr->pRight!=0 );
nRight = sqlite3ExprVectorSize(pExpr->pRight);
|
| ︙ | ︙ | |||
100479 100480 100481 100482 100483 100484 100485 |
Expr *pE /* Expression we are trying to match */
){
int i; /* Loop counter */
UNUSED_PARAMETER(pParse);
if( pE->op==TK_ID ){
| > > | | 100979 100980 100981 100982 100983 100984 100985 100986 100987 100988 100989 100990 100991 100992 100993 100994 100995 |
Expr *pE /* Expression we are trying to match */
){
int i; /* Loop counter */
UNUSED_PARAMETER(pParse);
if( pE->op==TK_ID ){
const char *zCol;
assert( !ExprHasProperty(pE, EP_IntValue) );
zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
if( pEList->a[i].eEName==ENAME_NAME
&& sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
){
return i+1;
}
}
|
| ︙ | ︙ | |||
101313 101314 101315 101316 101317 101318 101319 |
static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);
/*
** Return the affinity character for a single column of a table.
*/
SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table *pTab, int iCol){
| | | | 101815 101816 101817 101818 101819 101820 101821 101822 101823 101824 101825 101826 101827 101828 101829 101830 |
static void exprCodeBetween(Parse*,Expr*,int,void(*)(Parse*,Expr*,int,int),int);
static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);
/*
** Return the affinity character for a single column of a table.
*/
SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table *pTab, int iCol){
if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER;
return pTab->aCol[iCol].affinity;
}
/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
** or a sub-select with a column as the return value, then the
|
| ︙ | ︙ | |||
101344 101345 101346 101347 101348 101349 101350 |
|| pExpr->op==TK_IF_NULL_ROW
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
pExpr = pExpr->pLeft;
assert( pExpr!=0 );
}
op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
| | > > | | > | | > | 101846 101847 101848 101849 101850 101851 101852 101853 101854 101855 101856 101857 101858 101859 101860 101861 101862 101863 101864 101865 101866 101867 101868 101869 101870 101871 101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 101883 101884 101885 101886 101887 101888 |
|| pExpr->op==TK_IF_NULL_ROW
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
pExpr = pExpr->pLeft;
assert( pExpr!=0 );
}
op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
if( op==TK_COLUMN || op==TK_AGG_COLUMN ){
assert( ExprUseYTab(pExpr) );
if( pExpr->y.pTab ){
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}
}
if( op==TK_SELECT ){
assert( ExprUseXSelect(pExpr) );
assert( pExpr->x.pSelect!=0 );
assert( pExpr->x.pSelect->pEList!=0 );
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) );
assert( pExpr->iColumn < pExpr->iTable );
assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
return sqlite3ExprAffinity(
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
if( op==TK_VECTOR ){
assert( ExprUseXList(pExpr) );
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
return pExpr->affExpr;
}
/*
** Set the collating sequence for expression pExpr to be the collating
|
| ︙ | ︙ | |||
101428 101429 101430 101431 101432 101433 101434 |
** Skip over any TK_COLLATE operators and/or any unlikely()
** or likelihood() or likely() functions at the root of an
** expression.
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
| | | 101934 101935 101936 101937 101938 101939 101940 101941 101942 101943 101944 101945 101946 101947 101948 |
** Skip over any TK_COLLATE operators and/or any unlikely()
** or likelihood() or likely() functions at the root of an
** expression.
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
assert( ExprUseXList(pExpr) );
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
|
| ︙ | ︙ | |||
101461 101462 101463 101464 101465 101466 101467 |
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
sqlite3 *db = pParse->db;
CollSeq *pColl = 0;
const Expr *p = pExpr;
while( p ){
int op = p->op;
if( op==TK_REGISTER ) op = p->op2;
| | > | < | | | | | | | | > > > > | < < < | 101967 101968 101969 101970 101971 101972 101973 101974 101975 101976 101977 101978 101979 101980 101981 101982 101983 101984 101985 101986 101987 101988 101989 101990 101991 101992 101993 101994 101995 101996 101997 101998 101999 102000 102001 102002 102003 102004 102005 102006 102007 102008 102009 102010 102011 102012 102013 102014 102015 102016 |
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
sqlite3 *db = pParse->db;
CollSeq *pColl = 0;
const Expr *p = pExpr;
while( p ){
int op = p->op;
if( op==TK_REGISTER ) op = p->op2;
if( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER ){
assert( ExprUseYTab(p) );
if( p->y.pTab!=0 ){
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
int j = p->iColumn;
if( j>=0 ){
const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
}
break;
}
}
if( op==TK_CAST || op==TK_UPLUS ){
p = p->pLeft;
continue;
}
if( op==TK_VECTOR ){
assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
}
if( op==TK_COLLATE ){
assert( !ExprHasProperty(p, EP_IntValue) );
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
if( p->flags & EP_Collate ){
if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
p = p->pLeft;
}else{
Expr *pNext = p->pRight;
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( ExprUseXList(p) );
assert( p->x.pList==0 || p->pRight==0 );
if( p->x.pList!=0 && !db->mallocFailed ){
int i;
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
pNext = p->x.pList->a[i].pExpr;
break;
}
}
|
| ︙ | ︙ | |||
101578 101579 101580 101581 101582 101583 101584 |
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
| | | 102085 102086 102087 102088 102089 102090 102091 102092 102093 102094 102095 102096 102097 102098 102099 |
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}else if( ExprUseXSelect(pExpr) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( aff==0 ){
aff = SQLITE_AFF_BLOB;
}
return aff;
}
|
| ︙ | ︙ | |||
101718 101719 101720 101721 101722 101723 101724 101725 101726 101727 101728 101729 101730 101731 101732 101733 |
** is a sub-select, return the number of columns in the sub-select. For
** any other type of expression, return 1.
*/
SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr){
u8 op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
if( op==TK_VECTOR ){
return pExpr->x.pList->nExpr;
}else if( op==TK_SELECT ){
return pExpr->x.pSelect->pEList->nExpr;
}else{
return 1;
}
}
/*
| > > | 102225 102226 102227 102228 102229 102230 102231 102232 102233 102234 102235 102236 102237 102238 102239 102240 102241 102242 |
** is a sub-select, return the number of columns in the sub-select. For
** any other type of expression, return 1.
*/
SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr){
u8 op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
if( op==TK_VECTOR ){
assert( ExprUseXList(pExpr) );
return pExpr->x.pList->nExpr;
}else if( op==TK_SELECT ){
assert( ExprUseXSelect(pExpr) );
return pExpr->x.pSelect->pEList->nExpr;
}else{
return 1;
}
}
/*
|
| ︙ | ︙ | |||
101746 101747 101748 101749 101750 101751 101752 101753 101754 101755 101756 101757 101758 101759 101760 101761 |
** been positioned.
*/
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
assert( i<sqlite3ExprVectorSize(pVector) || pVector->op==TK_ERROR );
if( sqlite3ExprIsVector(pVector) ){
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
return pVector->x.pSelect->pEList->a[i].pExpr;
}else{
return pVector->x.pList->a[i].pExpr;
}
}
return pVector;
}
/*
| > > | 102255 102256 102257 102258 102259 102260 102261 102262 102263 102264 102265 102266 102267 102268 102269 102270 102271 102272 |
** been positioned.
*/
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
assert( i<sqlite3ExprVectorSize(pVector) || pVector->op==TK_ERROR );
if( sqlite3ExprIsVector(pVector) ){
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
return pVector->x.pSelect->pEList->a[i].pExpr;
}else{
assert( ExprUseXList(pVector) );
return pVector->x.pList->a[i].pExpr;
}
}
return pVector;
}
/*
|
| ︙ | ︙ | |||
101783 101784 101785 101786 101787 101788 101789 |
Parse *pParse, /* Parsing context */
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
int iField, /* Which column of the vector to return */
int nField /* Total number of columns in the vector */
){
Expr *pRet;
if( pVector->op==TK_SELECT ){
| | | 102294 102295 102296 102297 102298 102299 102300 102301 102302 102303 102304 102305 102306 102307 102308 |
Parse *pParse, /* Parsing context */
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
int iField, /* Which column of the vector to return */
int nField /* Total number of columns in the vector */
){
Expr *pRet;
if( pVector->op==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
/* The TK_SELECT_COLUMN Expr node:
**
** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
|
| ︙ | ︙ | |||
101808 101809 101810 101811 101812 101813 101814 |
if( pRet ){
pRet->iTable = nField;
pRet->iColumn = iField;
pRet->pLeft = pVector;
}
}else{
if( pVector->op==TK_VECTOR ){
| > > | | 102319 102320 102321 102322 102323 102324 102325 102326 102327 102328 102329 102330 102331 102332 102333 102334 102335 |
if( pRet ){
pRet->iTable = nField;
pRet->iColumn = iField;
pRet->pLeft = pVector;
}
}else{
if( pVector->op==TK_VECTOR ){
Expr **ppVector;
assert( ExprUseXList(pVector) );
ppVector = &pVector->x.pList->a[iField].pExpr;
pVector = *ppVector;
if( IN_RENAME_OBJECT ){
/* This must be a vector UPDATE inside a trigger */
*ppVector = 0;
return pVector;
}
}
|
| ︙ | ︙ | |||
101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 101883 101884 101885 101886 101887 101888 101889 |
u8 op = pVector->op;
assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR );
if( op==TK_REGISTER ){
*ppExpr = sqlite3VectorFieldSubexpr(pVector, iField);
return pVector->iTable+iField;
}
if( op==TK_SELECT ){
*ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
return regSelect+iField;
}
if( op==TK_VECTOR ){
*ppExpr = pVector->x.pList->a[iField].pExpr;
return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
}
return 0;
}
/*
| > > | 102385 102386 102387 102388 102389 102390 102391 102392 102393 102394 102395 102396 102397 102398 102399 102400 102401 102402 102403 102404 |
u8 op = pVector->op;
assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR );
if( op==TK_REGISTER ){
*ppExpr = sqlite3VectorFieldSubexpr(pVector, iField);
return pVector->iTable+iField;
}
if( op==TK_SELECT ){
assert( ExprUseXSelect(pVector) );
*ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
return regSelect+iField;
}
if( op==TK_VECTOR ){
assert( ExprUseXList(pVector) );
*ppExpr = pVector->x.pList->a[iField].pExpr;
return sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
}
return 0;
}
/*
|
| ︙ | ︙ | |||
102050 102051 102052 102053 102054 102055 102056 |
** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
** if appropriate.
*/
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
| | | 102565 102566 102567 102568 102569 102570 102571 102572 102573 102574 102575 102576 102577 102578 102579 |
** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
** if appropriate.
*/
static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
if( ExprUseXSelect(p) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else if( p->x.pList ){
heightOfExprList(p->x.pList, &nHeight);
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
p->nHeight = nHeight + 1;
}
|
| ︙ | ︙ | |||
102089 102090 102091 102092 102093 102094 102095 |
#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */
/*
** Propagate all EP_Propagate flags from the Expr.x.pList into
** Expr.flags.
*/
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
if( pParse->nErr ) return;
| | | 102604 102605 102606 102607 102608 102609 102610 102611 102612 102613 102614 102615 102616 102617 102618 |
#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */
/*
** Propagate all EP_Propagate flags from the Expr.x.pList into
** Expr.flags.
*/
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
if( pParse->nErr ) return;
if( p && ExprUseXList(p) && p->x.pList ){
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
}
#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
/*
|
| ︙ | ︙ | |||
102273 102274 102275 102276 102277 102278 102279 |
SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
int ii;
Select *pRet = 0;
assert( nElem>1 );
for(ii=0; ii<pEList->nExpr; ii++){
Select *pSel;
Expr *pExpr = pEList->a[ii].pExpr;
| | > > > > > > > | 102788 102789 102790 102791 102792 102793 102794 102795 102796 102797 102798 102799 102800 102801 102802 102803 102804 102805 102806 102807 102808 102809 102810 102811 102812 102813 102814 102815 |
SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
int ii;
Select *pRet = 0;
assert( nElem>1 );
for(ii=0; ii<pEList->nExpr; ii++){
Select *pSel;
Expr *pExpr = pEList->a[ii].pExpr;
int nExprElem;
if( pExpr->op==TK_VECTOR ){
assert( ExprUseXList(pExpr) );
nExprElem = pExpr->x.pList->nExpr;
}else{
nExprElem = 1;
}
if( nExprElem!=nElem ){
sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
nExprElem, nExprElem>1?"s":"", nElem
);
break;
}
assert( ExprUseXList(pExpr) );
pSel = sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
pExpr->x.pList = 0;
if( pSel ){
if( pRet ){
pSel->op = TK_ALL;
pSel->pPrior = pRet;
}
|
| ︙ | ︙ | |||
102349 102350 102351 102352 102353 102354 102355 |
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
&& !pParse->nested
){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
pNew->x.pList = pList;
ExprSetProperty(pNew, EP_HasFunc);
| | | 102871 102872 102873 102874 102875 102876 102877 102878 102879 102880 102881 102882 102883 102884 102885 |
&& pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
&& !pParse->nested
){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
pNew->x.pList = pList;
ExprSetProperty(pNew, EP_HasFunc);
assert( ExprUseXList(pNew) );
sqlite3ExprSetHeightAndFlags(pParse, pNew);
if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
return pNew;
}
/*
** Check to see if a function is usable according to current access
|
| ︙ | ︙ | |||
102475 102476 102477 102478 102479 102480 102481 |
}
/*
** Recursively delete an expression tree.
*/
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
| < | | | | < | > | | | > > > | 102997 102998 102999 103000 103001 103002 103003 103004 103005 103006 103007 103008 103009 103010 103011 103012 103013 103014 103015 103016 103017 103018 103019 103020 103021 103022 103023 103024 103025 103026 103027 103028 103029 103030 103031 103032 103033 103034 103035 103036 103037 103038 103039 103040 103041 103042 103043 103044 103045 |
}
/*
** Recursively delete an expression tree.
*/
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
assert( !ExprUseUValue(p) || p->u.iValue>=0 );
assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
assert( p->pRight==0 );
assert( !ExprUseXSelect(p) || p->x.pSelect==0 );
assert( !ExprUseXList(p) || p->x.pList==0 );
}
#endif
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
if( p->pRight ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlite3ExprDeleteNN(db, p->pRight);
}else if( ExprUseXSelect(p) ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlite3SelectDelete(db, p->x.pSelect);
}else{
sqlite3ExprListDelete(db, p->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(p, EP_WinFunc) ){
sqlite3WindowDelete(db, p->y.pWin);
}
#endif
}
}
if( ExprHasProperty(p, EP_MemToken) ){
assert( !ExprHasProperty(p, EP_IntValue) );
sqlite3DbFree(db, p->u.zToken);
}
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
|
| ︙ | ︙ | |||
102723 102724 102725 102726 102727 102728 102729 |
if( nToken ){
char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->u.zToken, nToken);
}
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
| | | 103247 103248 103249 103250 103251 103252 103253 103254 103255 103256 103257 103258 103259 103260 103261 |
if( nToken ){
char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->u.zToken, nToken);
}
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprUseXSelect(p) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
}else{
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, dupFlags);
}
}
/* Fill in pNew->pLeft and pNew->pRight. */
|
| ︙ | ︙ | |||
103017 103018 103019 103020 103021 103022 103023 |
pp = &pNew->pPrior;
pNext = pNew;
}
return pRet;
}
#else
| | | 103541 103542 103543 103544 103545 103546 103547 103548 103549 103550 103551 103552 103553 103554 103555 |
pp = &pNew->pPrior;
pNext = pNew;
}
return pRet;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *p, int flags){
assert( p==0 );
return 0;
}
#endif
/*
|
| ︙ | ︙ | |||
103350 103351 103352 103353 103354 103355 103356 |
** If the input expression is an ID with the name "true" or "false"
** then convert it into an TK_TRUEFALSE term. Return non-zero if
** the conversion happened, and zero if the expression is unaltered.
*/
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
u32 v;
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
| | > | 103874 103875 103876 103877 103878 103879 103880 103881 103882 103883 103884 103885 103886 103887 103888 103889 103890 103891 103892 103893 103894 103895 103896 103897 103898 103899 103900 103901 103902 103903 103904 103905 |
** If the input expression is an ID with the name "true" or "false"
** then convert it into an TK_TRUEFALSE term. Return non-zero if
** the conversion happened, and zero if the expression is unaltered.
*/
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
u32 v;
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
if( !ExprHasProperty(pExpr, EP_Quoted|EP_IntValue)
&& (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0
){
pExpr->op = TK_TRUEFALSE;
ExprSetProperty(pExpr, v);
return 1;
}
return 0;
}
/*
** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE
** and 0 if it is FALSE.
*/
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){
pExpr = sqlite3ExprSkipCollate((Expr*)pExpr);
assert( pExpr->op==TK_TRUEFALSE );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
|| sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
return pExpr->u.zToken[4]==0;
}
/*
** If pExpr is an AND or OR expression, try to simplify it by eliminating
|
| ︙ | ︙ | |||
103571 103572 103573 103574 103575 103576 103577 |
if( sqlite3IsBinary(pColl) ){
return WRC_Prune;
}
}
}
/* Check if pExpr is a sub-select. If so, consider it variable. */
| | | 104096 104097 104098 104099 104100 104101 104102 104103 104104 104105 104106 104107 104108 104109 104110 |
if( sqlite3IsBinary(pColl) ){
return WRC_Prune;
}
}
}
/* Check if pExpr is a sub-select. If so, consider it variable. */
if( ExprUseXSelect(pExpr) ){
pWalker->eCode = 0;
return WRC_Abort;
}
return exprNodeIsConstant(pWalker, pExpr);
}
|
| ︙ | ︙ | |||
103678 103679 103680 103681 103682 103683 103684 |
}
switch( p->op ){
case TK_UPLUS: {
rc = sqlite3ExprIsInteger(p->pLeft, pValue);
break;
}
case TK_UMINUS: {
| | | | 104203 104204 104205 104206 104207 104208 104209 104210 104211 104212 104213 104214 104215 104216 104217 104218 104219 |
}
switch( p->op ){
case TK_UPLUS: {
rc = sqlite3ExprIsInteger(p->pLeft, pValue);
break;
}
case TK_UMINUS: {
int v = 0;
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
break;
}
default: break;
}
|
| ︙ | ︙ | |||
103721 103722 103723 103724 103725 103726 103727 103728 103729 103730 |
switch( op ){
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
case TK_BLOB:
return 0;
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0
| > | | 104246 104247 104248 104249 104250 104251 104252 104253 104254 104255 104256 104257 104258 104259 104260 104261 104262 104263 104264 |
switch( op ){
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
case TK_BLOB:
return 0;
case TK_COLUMN:
assert( ExprUseYTab(p) );
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0
&& p->y.pTab->aCol!=0 /* Possible due to prior error */
&& p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
}
/*
|
| ︙ | ︙ | |||
103798 103799 103800 103801 103802 103803 103804 |
#ifndef SQLITE_OMIT_SUBQUERY
static Select *isCandidateForInOpt(const Expr *pX){
Select *p;
SrcList *pSrc;
ExprList *pEList;
Table *pTab;
int i;
| | | 104324 104325 104326 104327 104328 104329 104330 104331 104332 104333 104334 104335 104336 104337 104338 |
#ifndef SQLITE_OMIT_SUBQUERY
static Select *isCandidateForInOpt(const Expr *pX){
Select *p;
SrcList *pSrc;
ExprList *pEList;
Table *pTab;
int i;
if( !ExprUseXSelect(pX) ) return 0; /* Not a subquery */
if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
p = pX->x.pSelect;
if( p->pPrior ) return 0; /* Not a compound SELECT */
if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
return 0; /* No DISTINCT keyword and no aggregate functions */
|
| ︙ | ︙ | |||
103969 103970 103971 103972 103973 103974 103975 | mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether ** or not NULL is actually possible (it may not be, for example, due ** to NOT NULL constraints in the schema). If no NULL values are possible, ** set prRhsHasNull to 0 before continuing. */ | | | 104495 104496 104497 104498 104499 104500 104501 104502 104503 104504 104505 104506 104507 104508 104509 |
mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
/* If the RHS of this IN(...) operator is a SELECT, and if it matters
** whether or not the SELECT result contains NULL values, check whether
** or not NULL is actually possible (it may not be, for example, due
** to NOT NULL constraints in the schema). If no NULL values are possible,
** set prRhsHasNull to 0 before continuing. */
if( prRhsHasNull && ExprUseXSelect(pX) ){
int i;
ExprList *pEList = pX->x.pSelect->pEList;
for(i=0; i<pEList->nExpr; i++){
if( sqlite3ExprCanBeNull(pEList->a[i].pExpr) ) break;
}
if( i==pEList->nExpr ){
prRhsHasNull = 0;
|
| ︙ | ︙ | |||
104070 104071 104072 104073 104074 104075 104076 |
colUsed = 0; /* Columns of index used so far */
for(i=0; i<nExpr; i++){
Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
Expr *pRhs = pEList->a[i].pExpr;
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
int j;
| | > | 104596 104597 104598 104599 104600 104601 104602 104603 104604 104605 104606 104607 104608 104609 104610 104611 |
colUsed = 0; /* Columns of index used so far */
for(i=0; i<nExpr; i++){
Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
Expr *pRhs = pEList->a[i].pExpr;
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
int j;
assert( pReq!=0 || pRhs->iColumn==XN_ROWID
|| pParse->nErr || db->mallocFailed );
for(j=0; j<nExpr; j++){
if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
assert( pIdx->azColl[j] );
if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){
continue;
}
break;
|
| ︙ | ︙ | |||
104125 104126 104127 104128 104129 104130 104131 | ** and the RHS of the IN operator is a list, not a subquery ** and the RHS is not constant or has two or fewer terms, ** then it is not worth creating an ephemeral table to evaluate ** the IN operator so return IN_INDEX_NOOP. */ if( eType==0 && (inFlags & IN_INDEX_NOOP_OK) | | | 104652 104653 104654 104655 104656 104657 104658 104659 104660 104661 104662 104663 104664 104665 104666 |
** and the RHS of the IN operator is a list, not a subquery
** and the RHS is not constant or has two or fewer terms,
** then it is not worth creating an ephemeral table to evaluate
** the IN operator so return IN_INDEX_NOOP.
*/
if( eType==0
&& (inFlags & IN_INDEX_NOOP_OK)
&& ExprUseXList(pX)
&& (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
){
eType = IN_INDEX_NOOP;
}
if( eType==0 ){
/* Could not find an existing table or index to use as the RHS b-tree.
|
| ︙ | ︙ | |||
104173 104174 104175 104176 104177 104178 104179 |
**
** It is the responsibility of the caller to ensure that the returned
** string is eventually freed using sqlite3DbFree().
*/
static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlite3ExprVectorSize(pLeft);
| | | 104700 104701 104702 104703 104704 104705 104706 104707 104708 104709 104710 104711 104712 104713 104714 |
**
** It is the responsibility of the caller to ensure that the returned
** string is eventually freed using sqlite3DbFree().
*/
static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlite3ExprVectorSize(pLeft);
Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0;
char *zRet;
assert( pExpr->op==TK_IN );
zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; i<nVal; i++){
|
| ︙ | ︙ | |||
104223 104224 104225 104226 104227 104228 104229 |
**
** Or, if it is a regular scalar vector:
**
** "row value misused"
*/
SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
| | | 104750 104751 104752 104753 104754 104755 104756 104757 104758 104759 104760 104761 104762 104763 104764 |
**
** Or, if it is a regular scalar vector:
**
** "row value misused"
*/
SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
if( ExprUseXSelect(pExpr) ){
sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
}else
#endif
{
sqlite3ErrorMsg(pParse, "row value misused");
}
}
|
| ︙ | ︙ | |||
104287 104288 104289 104290 104291 104292 104293 |
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
/* Reuse of the RHS is allowed */
/* If this routine has already been coded, but the previous code
** might not have been invoked yet, so invoke it now as a subroutine.
*/
if( ExprHasProperty(pExpr, EP_Subrtn) ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
| | > > | | | 104814 104815 104816 104817 104818 104819 104820 104821 104822 104823 104824 104825 104826 104827 104828 104829 104830 104831 104832 104833 104834 104835 104836 104837 104838 104839 104840 104841 104842 104843 104844 104845 104846 104847 104848 104849 104850 104851 104852 104853 104854 104855 104856 104857 104858 104859 104860 104861 104862 104863 104864 104865 104866 104867 104868 104869 104870 |
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
/* Reuse of the RHS is allowed */
/* If this routine has already been coded, but the previous code
** might not have been invoked yet, so invoke it now as a subroutine.
*/
if( ExprHasProperty(pExpr, EP_Subrtn) ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
pExpr->x.pSelect->selId));
}
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
return;
}
/* Begin coding the subroutine */
assert( !ExprUseYWin(pExpr) );
ExprSetProperty(pExpr, EP_Subrtn);
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
VdbeComment((v, "return address"));
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
/* Check to see if this is a vector IN operator */
pLeft = pExpr->pLeft;
nVal = sqlite3ExprVectorSize(pLeft);
/* Construct the ephemeral table that will contain the content of
** RHS of the IN operator.
*/
pExpr->iTable = iTab;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
if( ExprUseXSelect(pExpr) ){
VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
}else{
VdbeComment((v, "RHS of IN operator"));
}
#endif
pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
if( ExprUseXSelect(pExpr) ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
** table allocated and opened above.
*/
Select *pSelect = pExpr->x.pSelect;
ExprList *pEList = pSelect->pEList;
|
| ︙ | ︙ | |||
104425 104426 104427 104428 104429 104430 104431 104432 104433 104434 104435 104436 104437 104438 |
}
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
}
}
#endif /* SQLITE_OMIT_SUBQUERY */
| > | 104954 104955 104956 104957 104958 104959 104960 104961 104962 104963 104964 104965 104966 104967 104968 |
}
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
}
}
#endif /* SQLITE_OMIT_SUBQUERY */
|
| ︙ | ︙ | |||
104461 104462 104463 104464 104465 104466 104467 | Vdbe *v = pParse->pVdbe; assert( v!=0 ); if( pParse->nErr ) return 0; testcase( pExpr->op==TK_EXISTS ); testcase( pExpr->op==TK_SELECT ); assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT ); | | > > > | 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 105003 105004 105005 105006 105007 105008 105009 105010 105011 105012 105013 105014 105015 105016 105017 105018 105019 105020 |
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
if( pParse->nErr ) return 0;
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
assert( ExprUseXSelect(pExpr) );
pSel = pExpr->x.pSelect;
/* If this routine has already been coded, then invoke it as a
** subroutine. */
if( ExprHasProperty(pExpr, EP_Subrtn) ){
ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
return pExpr->iTable;
}
/* Begin coding the subroutine */
assert( !ExprUseYWin(pExpr) );
assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
ExprSetProperty(pExpr, EP_Subrtn);
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
VdbeComment((v, "return address"));
|
| ︙ | ︙ | |||
104553 104554 104555 104556 104557 104558 104559 104560 104561 104562 104563 104564 104565 104566 104567 104568 104569 104570 104571 104572 104573 104574 104575 |
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
}
/* Subroutine return */
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Expr pIn is an IN(...) expression. This function checks that the
** sub-select on the RHS of the IN() operator has the same number of
** columns as the vector on the LHS. Or, if the RHS of the IN() is not
** a sub-query, that the LHS is a vector of size 1.
*/
SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
| > | | 105086 105087 105088 105089 105090 105091 105092 105093 105094 105095 105096 105097 105098 105099 105100 105101 105102 105103 105104 105105 105106 105107 105108 105109 105110 105111 105112 105113 105114 105115 105116 105117 |
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
}
/* Subroutine return */
assert( ExprUseYSub(pExpr) );
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
sqlite3ClearTempRegCache(pParse);
return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Expr pIn is an IN(...) expression. This function checks that the
** sub-select on the RHS of the IN() operator has the same number of
** columns as the vector on the LHS. Or, if the RHS of the IN() is not
** a sub-query, that the LHS is a vector of size 1.
*/
SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
int nVector = sqlite3ExprVectorSize(pIn->pLeft);
if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
return 1;
}
}else if( nVector!=1 ){
sqlite3VectorErrorMsg(pParse, pIn->pLeft);
return 1;
|
| ︙ | ︙ | |||
104703 104704 104705 104706 104707 104708 104709 |
/* If sqlite3FindInIndex() did not find or create an index that is
** suitable for evaluating the IN operator, then evaluate using a
** sequence of comparisons.
**
** This is step (1) in the in-operator.md optimized algorithm.
*/
if( eType==IN_INDEX_NOOP ){
| | | | > > | 105237 105238 105239 105240 105241 105242 105243 105244 105245 105246 105247 105248 105249 105250 105251 105252 105253 105254 105255 105256 105257 105258 105259 |
/* If sqlite3FindInIndex() did not find or create an index that is
** suitable for evaluating the IN operator, then evaluate using a
** sequence of comparisons.
**
** This is step (1) in the in-operator.md optimized algorithm.
*/
if( eType==IN_INDEX_NOOP ){
ExprList *pList;
CollSeq *pColl;
int labelOk = sqlite3VdbeMakeLabel(pParse);
int r2, regToFree;
int regCkNull = 0;
int ii;
assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
if( destIfNull!=destIfFalse ){
regCkNull = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
}
for(ii=0; ii<pList->nExpr; ii++){
r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree);
if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
|
| ︙ | ︙ | |||
105095 105096 105097 105098 105099 105100 105101 105102 105103 105104 105105 105106 105107 105108 |
#else
iResult = sqlite3CodeSubselect(pParse, p);
#endif
}else{
int i;
iResult = pParse->nMem+1;
pParse->nMem += nResult;
for(i=0; i<nResult; i++){
sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
}
}
}
return iResult;
}
| > | 105631 105632 105633 105634 105635 105636 105637 105638 105639 105640 105641 105642 105643 105644 105645 |
#else
iResult = sqlite3CodeSubselect(pParse, p);
#endif
}else{
int i;
iResult = pParse->nMem+1;
pParse->nMem += nResult;
assert( ExprUseXList(p) );
for(i=0; i<nResult; i++){
sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
}
}
}
return iResult;
}
|
| ︙ | ︙ | |||
105293 105294 105295 105296 105297 105298 105299 105300 105301 105302 105303 105304 105305 105306 |
** constraints, and that constant is coded by the pExpr->pLeft
** expresssion. However, make sure the constant has the correct
** datatype by applying the Affinity of the table column to the
** constant.
*/
int aff;
iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
if( pExpr->y.pTab ){
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
aff = pExpr->affExpr;
}
if( aff>SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
| > | 105830 105831 105832 105833 105834 105835 105836 105837 105838 105839 105840 105841 105842 105843 105844 |
** constraints, and that constant is coded by the pExpr->pLeft
** expresssion. However, make sure the constant has the correct
** datatype by applying the Affinity of the table column to the
** constant.
*/
int aff;
iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
assert( ExprUseYTab(pExpr) );
if( pExpr->y.pTab ){
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
aff = pExpr->affExpr;
}
if( aff>SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
|
| ︙ | ︙ | |||
105316 105317 105318 105319 105320 105321 105322 |
/* Other columns in the same row for CHECK constraints or
** generated columns or for inserting into partial index.
** The row is unpacked into registers beginning at
** 0-(pParse->iSelfTab). The rowid (if any) is in a register
** immediately prior to the first column.
*/
Column *pCol;
| | > > | 105854 105855 105856 105857 105858 105859 105860 105861 105862 105863 105864 105865 105866 105867 105868 105869 105870 105871 105872 |
/* Other columns in the same row for CHECK constraints or
** generated columns or for inserting into partial index.
** The row is unpacked into registers beginning at
** 0-(pParse->iSelfTab). The rowid (if any) is in a register
** immediately prior to the first column.
*/
Column *pCol;
Table *pTab;
int iSrc;
int iCol = pExpr->iColumn;
assert( ExprUseYTab(pExpr) );
pTab = pExpr->y.pTab;
assert( pTab!=0 );
assert( iCol>=XN_ROWID );
assert( iCol<pTab->nCol );
if( iCol<0 ){
return -1-pParse->iSelfTab;
}
pCol = pTab->aCol + iCol;
|
| ︙ | ︙ | |||
105356 105357 105358 105359 105360 105361 105362 105363 105364 105365 105366 105367 105368 105369 |
}
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */
iTab = pParse->iSelfTab - 1;
}
}
iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
return iReg;
| > | 105896 105897 105898 105899 105900 105901 105902 105903 105904 105905 105906 105907 105908 105909 105910 |
}
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */
iTab = pParse->iSelfTab - 1;
}
}
assert( ExprUseYTab(pExpr) );
iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
}
return iReg;
|
| ︙ | ︙ | |||
105433 105434 105435 105436 105437 105438 105439 105440 105441 105442 105443 105444 105445 105446 |
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
if( inReg!=target ){
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
inReg = target;
}
sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlite3AffinityType(pExpr->u.zToken, 0));
return inReg;
}
#endif /* SQLITE_OMIT_CAST */
case TK_IS:
case TK_ISNOT:
| > | 105974 105975 105976 105977 105978 105979 105980 105981 105982 105983 105984 105985 105986 105987 105988 |
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
if( inReg!=target ){
sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
inReg = target;
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlite3AffinityType(pExpr->u.zToken, 0));
return inReg;
}
#endif /* SQLITE_OMIT_CAST */
case TK_IS:
case TK_ISNOT:
|
| ︙ | ︙ | |||
105600 105601 105602 105603 105604 105605 105606 |
#endif
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
/* SQL functions can be expensive. So try to avoid running them
** multiple times if we know they always give the same result */
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
}
| | | | 106142 106143 106144 106145 106146 106147 106148 106149 106150 106151 106152 106153 106154 106155 106156 106157 |
#endif
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
/* SQL functions can be expensive. So try to avoid running them
** multiple times if we know they always give the same result */
return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
}
assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
assert( ExprUseXList(pExpr) );
pFarg = pExpr->x.pList;
nFarg = pFarg ? pFarg->nExpr : 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
zId = pExpr->u.zToken;
pDef = sqlite3FindFunction(db, zId, nFarg, enc, 0);
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
if( pDef==0 && pParse->explain ){
|
| ︙ | ︙ | |||
105690 105691 105692 105693 105694 105695 105696 |
}
#endif
if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
| | | 106232 106233 106234 106235 106236 106237 106238 106239 106240 106241 106242 106243 106244 106245 106246 |
}
#endif
if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
if( (pDef->funcFlags & SQLITE_FUNC_OFFSET)!=0 && ALWAYS(pFarg!=0) ){
Expr *pArg = pFarg->a[0].pExpr;
if( pArg->op==TK_COLUMN ){
sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
}else
|
| ︙ | ︙ | |||
105720 105721 105722 105723 105724 105725 105726 |
case TK_EXISTS:
case TK_SELECT: {
int nCol;
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
if( pParse->db->mallocFailed ){
return 0;
| > > | > | 106262 106263 106264 106265 106266 106267 106268 106269 106270 106271 106272 106273 106274 106275 106276 106277 106278 106279 |
case TK_EXISTS:
case TK_SELECT: {
int nCol;
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
if( pParse->db->mallocFailed ){
return 0;
}else if( op==TK_SELECT
&& ALWAYS( ExprUseXSelect(pExpr) )
&& (nCol = pExpr->x.pSelect->pEList->nExpr)!=1
){
sqlite3SubselectError(pParse, nCol, 1);
}else{
return sqlite3CodeSubselect(pParse, pExpr);
}
break;
}
case TK_SELECT_COLUMN: {
|
| ︙ | ︙ | |||
105802 105803 105804 105805 105806 105807 105808 |
**
** Then p1 is interpreted as follows:
**
** p1==0 -> old.rowid p1==3 -> new.rowid
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
| > > > > > | | | | 106347 106348 106349 106350 106351 106352 106353 106354 106355 106356 106357 106358 106359 106360 106361 106362 106363 106364 106365 106366 106367 106368 |
**
** Then p1 is interpreted as follows:
**
** p1==0 -> old.rowid p1==3 -> new.rowid
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab;
int iCol;
int p1;
assert( ExprUseYTab(pExpr) );
pTab = pExpr->y.pTab;
iCol = pExpr->iColumn;
p1 = pExpr->iTable * (pTab->nCol+1) + 1
+ sqlite3TableColumnToStorage(pTab, iCol);
assert( pExpr->iTable==0 || pExpr->iTable==1 );
assert( iCol>=-1 && iCol<pTab->nCol );
assert( pTab->iPKey<0 || iCol!=pTab->iPKey );
assert( p1>=0 && p1<(pTab->nCol*2+2) );
|
| ︙ | ︙ | |||
105892 105893 105894 105895 105896 105897 105898 |
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
Expr *pDel = 0;
sqlite3 *db = pParse->db;
| | | 106442 106443 106444 106445 106446 106447 106448 106449 106450 106451 106452 106453 106454 106455 106456 |
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
Expr *pDel = 0;
sqlite3 *db = pParse->db;
assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 );
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(pParse);
if( (pX = pExpr->pLeft)!=0 ){
pDel = sqlite3ExprDup(db, pX, 0);
|
| ︙ | ︙ | |||
106237 106238 106239 106240 106241 106242 106243 | Expr *pDel = 0; sqlite3 *db = pParse->db; memset(&compLeft, 0, sizeof(Expr)); memset(&compRight, 0, sizeof(Expr)); memset(&exprAnd, 0, sizeof(Expr)); | | | 106787 106788 106789 106790 106791 106792 106793 106794 106795 106796 106797 106798 106799 106800 106801 |
Expr *pDel = 0;
sqlite3 *db = pParse->db;
memset(&compLeft, 0, sizeof(Expr));
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
assert( ExprUseXList(pExpr) );
pDel = sqlite3ExprDup(db, pExpr->pLeft, 0);
if( db->mallocFailed==0 ){
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.pLeft = pDel;
|
| ︙ | ︙ | |||
106712 106713 106714 106715 106716 106717 106718 |
return 1;
}
if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
return 1;
}
return 2;
}
| > > | > > > > | > | 107262 107263 107264 107265 107266 107267 107268 107269 107270 107271 107272 107273 107274 107275 107276 107277 107278 107279 107280 107281 107282 107283 107284 107285 107286 107287 107288 107289 107290 107291 107292 107293 107294 107295 107296 107297 107298 107299 107300 107301 |
return 1;
}
if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
return 1;
}
return 2;
}
assert( !ExprHasProperty(pA, EP_IntValue) );
assert( !ExprHasProperty(pB, EP_IntValue) );
if( pA->u.zToken ){
if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
#ifndef SQLITE_OMIT_WINDOWFUNC
assert( pA->op==pB->op );
if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){
return 2;
}
if( ExprHasProperty(pA,EP_WinFunc) ){
if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){
return 2;
}
}
#endif
}else if( pA->op==TK_NULL ){
return 0;
}else if( pA->op==TK_COLLATE ){
if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
}else
if( pB->u.zToken!=0
&& pA->op!=TK_COLUMN
&& pA->op!=TK_AGG_COLUMN
&& strcmp(pA->u.zToken,pB->u.zToken)!=0
){
return 2;
}
}
if( (pA->flags & (EP_Distinct|EP_Commuted))
!= (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
|
| ︙ | ︙ | |||
106819 106820 106821 106822 106823 106824 106825 |
assert( pNN );
if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){
return pNN->op!=TK_NULL;
}
switch( p->op ){
case TK_IN: {
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
| < | | > > | 107376 107377 107378 107379 107380 107381 107382 107383 107384 107385 107386 107387 107388 107389 107390 107391 107392 107393 107394 107395 107396 |
assert( pNN );
if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){
return pNN->op!=TK_NULL;
}
switch( p->op ){
case TK_IN: {
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) );
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
case TK_BETWEEN: {
ExprList *pList;
assert( ExprUseXList(p) );
pList = p->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
if( seenNot ) return 0;
if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1)
|| exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1)
){
return 1;
|
| ︙ | ︙ | |||
107001 107002 107003 107004 107005 107006 107007 |
testcase( pExpr->op==TK_NE );
testcase( pExpr->op==TK_LT );
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
/* The y.pTab=0 assignment in wherecode.c always happens after the
** impliesNotNullRow() test */
| > > | > | | > | | 107559 107560 107561 107562 107563 107564 107565 107566 107567 107568 107569 107570 107571 107572 107573 107574 107575 107576 107577 107578 107579 107580 |
testcase( pExpr->op==TK_NE );
testcase( pExpr->op==TK_LT );
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
/* The y.pTab=0 assignment in wherecode.c always happens after the
** impliesNotNullRow() test */
assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
if( (pLeft->op==TK_COLUMN
&& pLeft->y.pTab!=0
&& IsVirtual(pLeft->y.pTab))
|| (pRight->op==TK_COLUMN
&& pRight->y.pTab!=0
&& IsVirtual(pRight->y.pTab))
){
return WRC_Prune;
}
/* no break */ deliberate_fall_through
}
default:
return WRC_Continue;
|
| ︙ | ︙ | |||
107113 107114 107115 107116 107117 107118 107119 | w.xExprCallback = exprIdxCover; w.u.pIdxCover = &xcov; sqlite3WalkExpr(&w, pExpr); return !w.eCode; } | < | < | < | > | < | | | > | < > | > | | > > > > > | > > > > > > > > | > > > > > > | > > > | | > > > > | < < < < < < | > > | | | > > | < < > | < < < | > | | > > > > | > > | > > > | | < > | | > | > | < < < > > > > | > > > > > | 107675 107676 107677 107678 107679 107680 107681 107682 107683 107684 107685 107686 107687 107688 107689 107690 107691 107692 107693 107694 107695 107696 107697 107698 107699 107700 107701 107702 107703 107704 107705 107706 107707 107708 107709 107710 107711 107712 107713 107714 107715 107716 107717 107718 107719 107720 107721 107722 107723 107724 107725 107726 107727 107728 107729 107730 107731 107732 107733 107734 107735 107736 107737 107738 107739 107740 107741 107742 107743 107744 107745 107746 107747 107748 107749 107750 107751 107752 107753 107754 107755 107756 107757 107758 107759 107760 107761 107762 107763 107764 107765 107766 107767 107768 107769 107770 107771 107772 107773 107774 107775 107776 107777 107778 107779 107780 107781 107782 107783 107784 107785 107786 107787 107788 107789 107790 107791 107792 107793 107794 107795 107796 107797 107798 107799 107800 107801 107802 107803 107804 107805 107806 107807 |
w.xExprCallback = exprIdxCover;
w.u.pIdxCover = &xcov;
sqlite3WalkExpr(&w, pExpr);
return !w.eCode;
}
/* Structure used to pass information throught the Walker in order to
** implement sqlite3ReferencesSrcList().
*/
struct RefSrcList {
sqlite3 *db; /* Database connection used for sqlite3DbRealloc() */
SrcList *pRef; /* Looking for references to these tables */
i64 nExclude; /* Number of tables to exclude from the search */
int *aiExclude; /* Cursor IDs for tables to exclude from the search */
};
/*
** Walker SELECT callbacks for sqlite3ReferencesSrcList().
**
** When entering a new subquery on the pExpr argument, add all FROM clause
** entries for that subquery to the exclude list.
**
** When leaving the subquery, remove those entries from the exclude list.
*/
static int selectRefEnter(Walker *pWalker, Select *pSelect){
struct RefSrcList *p = pWalker->u.pRefSrcList;
SrcList *pSrc = pSelect->pSrc;
i64 i, j;
int *piNew;
if( pSrc->nSrc==0 ) return WRC_Continue;
j = p->nExclude;
p->nExclude += pSrc->nSrc;
piNew = sqlite3DbRealloc(p->db, p->aiExclude, p->nExclude*sizeof(int));
if( piNew==0 ){
p->nExclude = 0;
return WRC_Abort;
}else{
p->aiExclude = piNew;
}
for(i=0; i<pSrc->nSrc; i++, j++){
p->aiExclude[j] = pSrc->a[i].iCursor;
}
return WRC_Continue;
}
static void selectRefLeave(Walker *pWalker, Select *pSelect){
struct RefSrcList *p = pWalker->u.pRefSrcList;
SrcList *pSrc = pSelect->pSrc;
if( p->nExclude ){
assert( p->nExclude>=pSrc->nSrc );
p->nExclude -= pSrc->nSrc;
}
}
/* This is the Walker EXPR callback for sqlite3ReferencesSrcList().
**
** Set the 0x01 bit of pWalker->eCode if there is a reference to any
** of the tables shown in RefSrcList.pRef.
**
** Set the 0x02 bit of pWalker->eCode if there is a reference to a
** table is in neither RefSrcList.pRef nor RefSrcList.aiExclude.
*/
static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN
|| pExpr->op==TK_AGG_COLUMN
){
int i;
struct RefSrcList *p = pWalker->u.pRefSrcList;
SrcList *pSrc = p->pRef;
int nSrc = pSrc ? pSrc->nSrc : 0;
for(i=0; i<nSrc; i++){
if( pExpr->iTable==pSrc->a[i].iCursor ){
pWalker->eCode |= 1;
return WRC_Continue;
}
}
for(i=0; i<p->nExclude && p->aiExclude[i]!=pExpr->iTable; i++){}
if( i>=p->nExclude ){
pWalker->eCode |= 2;
}
}
return WRC_Continue;
}
/*
** Check to see if pExpr references any tables in pSrcList.
** Possible return values:
**
** 1 pExpr does references a table in pSrcList.
**
** 0 pExpr references some table that is not defined in either
** pSrcList or in subqueries of pExpr itself.
**
** -1 pExpr only references no tables at all, or it only
** references tables defined in subqueries of pExpr itself.
**
** As currently used, pExpr is always an aggregate function call. That
** fact is exploited for efficiency.
*/
SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){
Walker w;
struct RefSrcList x;
memset(&w, 0, sizeof(w));
memset(&x, 0, sizeof(x));
w.xExprCallback = exprRefToSrcList;
w.xSelectCallback = selectRefEnter;
w.xSelectCallback2 = selectRefLeave;
w.u.pRefSrcList = &x;
x.db = pParse->db;
x.pRef = pSrcList;
assert( pExpr->op==TK_AGG_FUNCTION );
assert( ExprUseXList(pExpr) );
sqlite3WalkExprList(&w, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
}
#endif
sqlite3DbFree(pParse->db, x.aiExclude);
if( w.eCode & 0x01 ){
return 1;
}else if( w.eCode ){
return 0;
}else{
return -1;
}
}
/*
** This is a Walker expression node callback.
**
** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo
** object that is referenced does not refer directly to the Expr. If
|
| ︙ | ︙ | |||
107329 107330 107331 107332 107333 107334 107335 107336 107337 107338 107339 107340 107341 107342 |
break;
}
}
if( (k>=pAggInfo->nColumn)
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
pCol->iSorterColumn = -1;
pCol->pCExpr = pExpr;
if( pAggInfo->pGroupBy ){
| > | 107928 107929 107930 107931 107932 107933 107934 107935 107936 107937 107938 107939 107940 107941 107942 |
break;
}
}
if( (k>=pAggInfo->nColumn)
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
pCol->iSorterColumn = -1;
pCol->pCExpr = pExpr;
if( pAggInfo->pGroupBy ){
|
| ︙ | ︙ | |||
107392 107393 107394 107395 107396 107397 107398 |
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pParse->db, pAggInfo);
if( i>=0 ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pItem = &pAggInfo->aFunc[i];
pItem->pFExpr = pExpr;
pItem->iMem = ++pParse->nMem;
| | | 107992 107993 107994 107995 107996 107997 107998 107999 108000 108001 108002 108003 108004 108005 108006 |
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pParse->db, pAggInfo);
if( i>=0 ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pItem = &pAggInfo->aFunc[i];
pItem->pFExpr = pExpr;
pItem->iMem = ++pParse->nMem;
assert( ExprUseUToken(pExpr) );
pItem->pFunc = sqlite3FindFunction(pParse->db,
pExpr->u.zToken,
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
if( pExpr->flags & EP_Distinct ){
pItem->iDistinct = pParse->nTab++;
}else{
pItem->iDistinct = -1;
|
| ︙ | ︙ | |||
107607 107608 107609 107610 107611 107612 107613 |
int bTemp, /* True if this is the temp db */
const char *zWhen, /* "when" part of error message */
int bNoDQS /* Do not allow DQS in the schema */
){
pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
"SELECT 1 "
| | | | | | 108207 108208 108209 108210 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 108222 108223 108224 108225 108226 108227 108228 108229 108230 108231 108232 108233 108234 108235 108236 108237 108238 108239 108240 108241 108242 108243 108244 108245 108246 108247 108248 108249 108250 108251 108252 108253 108254 108255 108256 108257 |
int bTemp, /* True if this is the temp db */
const char *zWhen, /* "when" part of error message */
int bNoDQS /* Do not allow DQS in the schema */
){
pParse->colNamesSet = 1;
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM \"%w\"." LEGACY_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
" AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
zDb,
zDb, bTemp, zWhen, bNoDQS
);
if( bTemp==0 ){
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM temp." LEGACY_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
" AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
zDb, zWhen, bNoDQS
);
}
}
/*
** Generate VM code to replace any double-quoted strings (but not double-quoted
** identifiers) within the "sql" column of the sqlite_schema table in
** database zDb with their single-quoted equivalents. If argument bTemp is
** not true, similarly update all SQL statements in the sqlite_schema table
** of the temp db.
*/
static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." LEGACY_SCHEMA_TABLE
" SET sql = sqlite_rename_quotefix(%Q, sql)"
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
);
if( bTemp==0 ){
sqlite3NestedParse(pParse,
"UPDATE temp." LEGACY_SCHEMA_TABLE
" SET sql = sqlite_rename_quotefix('temp', sql)"
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
);
}
}
|
| ︙ | ︙ | |||
107761 107762 107763 107764 107765 107766 107767 | /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; nTabName = sqlite3Utf8CharLen(zTabName, -1); /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in ** the schema to use the new table name. */ sqlite3NestedParse(pParse, | | | | 108361 108362 108363 108364 108365 108366 108367 108368 108369 108370 108371 108372 108373 108374 108375 108376 108377 108378 108379 108380 108381 108382 108383 108384 108385 |
/* figure out how many UTF-8 characters are in zName */
zTabName = pTab->zName;
nTabName = sqlite3Utf8CharLen(zTabName, -1);
/* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
** the schema to use the new table name. */
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "
"WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"
"AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
, zDb, zDb, zTabName, zName, (iDb==1), zTabName
);
/* Update the tbl_name and name columns of the sqlite_schema table
** as required. */
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE " SET "
"tbl_name = %Q, "
"name = CASE "
"WHEN type='table' THEN %Q "
"WHEN name LIKE 'sqliteX_autoindex%%' ESCAPE 'X' "
" AND type='index' THEN "
"'sqlite_autoindex_' || %Q || substr(name,%d+18) "
"ELSE name END "
|
| ︙ | ︙ | |||
107914 107915 107916 107917 107918 107919 107920 107921 107922 107923 107924 107925 107926 107927 |
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
assert( pDflt==0 || pDflt->op==TK_SPAN );
if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0;
}
if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a REFERENCES column with non-NULL default value");
}
if( pCol->notNull && !pDflt ){
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a NOT NULL column with default value NULL");
| > | 108514 108515 108516 108517 108518 108519 108520 108521 108522 108523 108524 108525 108526 108527 108528 |
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
assert( pDflt==0 || pDflt->op==TK_SPAN );
if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0;
}
assert( IsOrdinaryTable(pNew) );
if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a REFERENCES column with non-NULL default value");
}
if( pCol->notNull && !pDflt ){
sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a NOT NULL column with default value NULL");
|
| ︙ | ︙ | |||
107956 107957 107958 107959 107960 107961 107962 |
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
/* substr() operations on characters, but addColOffset is in bytes. So we
** have to use printf() to translate between these units: */
| | > | | 108557 108558 108559 108560 108561 108562 108563 108564 108565 108566 108567 108568 108569 108570 108571 108572 108573 108574 |
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
/* substr() operations on characters, but addColOffset is in bytes. So we
** have to use printf() to translate between these units: */
assert( IsOrdinaryTable(pTab) );
assert( IsOrdinaryTable(pNew) );
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = printf('%%.%ds, ',sql) || %Q"
" || substr(sql,1+length(printf('%%.%ds',sql))) "
"WHERE type = 'table' AND name = %Q",
zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
zTab
);
sqlite3DbFree(db, zCol);
|
| ︙ | ︙ | |||
107984 107985 107986 107987 107988 107989 107990 |
sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
sqlite3ReleaseTempReg(pParse, r1);
/* Reload the table definition */
| | | 108586 108587 108588 108589 108590 108591 108592 108593 108594 108595 108596 108597 108598 108599 108600 |
sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
sqlite3ReleaseTempReg(pParse, r1);
/* Reload the table definition */
renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd);
/* Verify that constraints are still satisfied */
if( pNew->pCheck!=0
|| (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
){
sqlite3NestedParse(pParse,
"SELECT CASE WHEN quick_check GLOB 'CHECK*'"
|
| ︙ | ︙ | |||
108050 108051 108052 108053 108054 108055 108056 108057 108058 108059 108060 108061 108062 108063 |
goto exit_begin_add_column;
}
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_begin_add_column;
}
sqlite3MayAbort(pParse);
assert( pTab->u.tab.addColOffset>0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the
** sqlite3AddColumn() function and friends to modify. But modify
** the name by adding an "sqlite_altertab_" prefix. By adding this
** prefix, we insure that the name will not collide with an existing
| > | 108652 108653 108654 108655 108656 108657 108658 108659 108660 108661 108662 108663 108664 108665 108666 |
goto exit_begin_add_column;
}
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_begin_add_column;
}
sqlite3MayAbort(pParse);
assert( IsOrdinaryTable(pTab) );
assert( pTab->u.tab.addColOffset>0 );
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the
** sqlite3AddColumn() function and friends to modify. But modify
** the name by adding an "sqlite_altertab_" prefix. By adding this
** prefix, we insure that the name will not collide with an existing
|
| ︙ | ︙ | |||
108080 108081 108082 108083 108084 108085 108086 |
}
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
pCol->hName = sqlite3StrIHash(pCol->zCnName);
}
| | | 108683 108684 108685 108686 108687 108688 108689 108690 108691 108692 108693 108694 108695 108696 108697 |
}
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
pCol->hName = sqlite3StrIHash(pCol->zCnName);
}
assert( IsOrdinaryTable(pNew) );
pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
pNew->pSchema = db->aDb[iDb].pSchema;
pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
pNew->nTabRef = 1;
exit_begin_add_column:
sqlite3SrcListDelete(db, pSrc);
|
| ︙ | ︙ | |||
108191 108192 108193 108194 108195 108196 108197 | */ sqlite3MayAbort(pParse); zNew = sqlite3NameFromToken(db, pNew); if( !zNew ) goto exit_rename_column; assert( pNew->n>0 ); bQuote = sqlite3Isquote(pNew->z[0]); sqlite3NestedParse(pParse, | | | | 108794 108795 108796 108797 108798 108799 108800 108801 108802 108803 108804 108805 108806 108807 108808 108809 108810 108811 108812 108813 108814 108815 108816 108817 108818 |
*/
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
if( !zNew ) goto exit_rename_column;
assert( pNew->n>0 );
bQuote = sqlite3Isquote(pNew->z[0]);
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
" AND (type != 'index' OR tbl_name = %Q)",
zDb,
zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
pTab->zName
);
sqlite3NestedParse(pParse,
"UPDATE temp." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
"WHERE type IN ('trigger', 'view')",
zDb, pTab->zName, iCol, zNew, bQuote
);
/* Drop and reload the database schema. */
renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
|
| ︙ | ︙ | |||
108349 108350 108351 108352 108353 108354 108355 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
Parse *pParse = pWalker->pParse;
sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr);
| > | > | 108952 108953 108954 108955 108956 108957 108958 108959 108960 108961 108962 108963 108964 108965 108966 108967 108968 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
Parse *pParse = pWalker->pParse;
sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr);
if( ExprUseYTab(pExpr) ){
sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab);
}
return WRC_Continue;
}
/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
|
| ︙ | ︙ | |||
108411 108412 108413 108414 108415 108416 108417 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
| > > | | 109016 109017 109018 109019 109020 109021 109022 109023 109024 109025 109026 109027 109028 109029 109030 109031 109032 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
testcase( p->selFlags & SF_View );
testcase( p->selFlags & SF_CopyCte );
if( p->selFlags & (SF_View|SF_CopyCte) ){
return WRC_Prune;
}
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
|
| ︙ | ︙ | |||
108548 108549 108550 108551 108552 108553 108554 108555 108556 108557 108558 108559 108560 108561 |
if( pExpr->op==TK_TRIGGER
&& pExpr->iColumn==p->iCol
&& pWalker->pParse->pTriggerTab==p->pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
&& p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
return WRC_Continue;
}
| > | 109155 109156 109157 109158 109159 109160 109161 109162 109163 109164 109165 109166 109167 109168 109169 |
if( pExpr->op==TK_TRIGGER
&& pExpr->iColumn==p->iCol
&& pWalker->pParse->pTriggerTab==p->pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
&& ALWAYS(ExprUseYTab(pExpr))
&& p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
return WRC_Continue;
}
|
| ︙ | ︙ | |||
108872 108873 108874 108875 108876 108877 108878 108879 108880 108881 108882 108883 108884 108885 |
rc = SQLITE_ERROR;
}else{
p->pTab->nTabRef++;
rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
}
}
}
sNC.pSrcList = pSrc;
if( rc==SQLITE_OK && pStep->pWhere ){
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
}
if( rc==SQLITE_OK ){
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
}
| > > > | 109480 109481 109482 109483 109484 109485 109486 109487 109488 109489 109490 109491 109492 109493 109494 109495 109496 |
rc = SQLITE_ERROR;
}else{
p->pTab->nTabRef++;
rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
}
}
}
if( rc==SQLITE_OK && db->mallocFailed ){
rc = SQLITE_NOMEM;
}
sNC.pSrcList = pSrc;
if( rc==SQLITE_OK && pStep->pWhere ){
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
}
if( rc==SQLITE_OK ){
rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
}
|
| ︙ | ︙ | |||
109078 109079 109080 109081 109082 109083 109084 |
Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable,
&sParse.pNewTable->aCol[i]);
sqlite3WalkExpr(&sWalker, pExpr);
}
#endif
}
| | | 109689 109690 109691 109692 109693 109694 109695 109696 109697 109698 109699 109700 109701 109702 109703 |
Expr *pExpr = sqlite3ColumnExpr(sParse.pNewTable,
&sParse.pNewTable->aCol[i]);
sqlite3WalkExpr(&sWalker, pExpr);
}
#endif
}
assert( IsOrdinaryTable(sParse.pNewTable) );
for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){
if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
}
if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
&& 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
|
| ︙ | ︙ | |||
109150 109151 109152 109153 109154 109155 109156 |
}
/*
** Walker expression callback used by "RENAME TABLE".
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
| | > > > | 109761 109762 109763 109764 109765 109766 109767 109768 109769 109770 109771 109772 109773 109774 109775 109776 109777 109778 |
}
/*
** Walker expression callback used by "RENAME TABLE".
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
if( pExpr->op==TK_COLUMN
&& ALWAYS(ExprUseYTab(pExpr))
&& p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
}
return WRC_Continue;
}
/*
** Walker select callback used by "RENAME TABLE".
|
| ︙ | ︙ | |||
109268 109269 109270 109271 109272 109273 109274 |
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
&& !IsVirtual(pTab)
){
FKey *pFKey;
| | | 109882 109883 109884 109885 109886 109887 109888 109889 109890 109891 109892 109893 109894 109895 109896 |
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
&& !IsVirtual(pTab)
){
FKey *pFKey;
assert( IsOrdinaryTable(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
}
}
}
#endif
|
| ︙ | ︙ | |||
109589 109590 109591 109592 109593 109594 109595 |
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
if( iCol<pTab->nCol-1 ){
RenameToken *pEnd;
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
zEnd = (const char*)pEnd->t.z;
}else{
| | | 110203 110204 110205 110206 110207 110208 110209 110210 110211 110212 110213 110214 110215 110216 110217 |
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
if( iCol<pTab->nCol-1 ){
RenameToken *pEnd;
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
zEnd = (const char*)pEnd->t.z;
}else{
assert( IsOrdinaryTable(pTab) );
zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
}
zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
sqlite3_free(zNew);
|
| ︙ | ︙ | |||
109671 109672 109673 109674 109675 109676 109677 | /* Edit the sqlite_schema table */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); zDb = db->aDb[iDb].zDbSName; renameTestSchema(pParse, zDb, iDb==1, "", 0); renameFixQuotes(pParse, zDb, iDb==1); sqlite3NestedParse(pParse, | | | 110285 110286 110287 110288 110289 110290 110291 110292 110293 110294 110295 110296 110297 110298 110299 |
/* Edit the sqlite_schema table */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 );
zDb = db->aDb[iDb].zDbSName;
renameTestSchema(pParse, zDb, iDb==1, "", 0);
renameFixQuotes(pParse, zDb, iDb==1);
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_drop_column(%d, sql, %d) "
"WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
, zDb, iDb, iCol, pTab->zName
);
/* Drop and reload the database schema. */
renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
|
| ︙ | ︙ | |||
110764 110765 110766 110767 110768 110769 110770 |
#endif
pParse->nMem = MAX(pParse->nMem, iMem);
v = sqlite3GetVdbe(pParse);
if( v==0 || NEVER(pTab==0) ){
return;
}
| | | 111378 111379 111380 111381 111382 111383 111384 111385 111386 111387 111388 111389 111390 111391 111392 |
#endif
pParse->nMem = MAX(pParse->nMem, iMem);
v = sqlite3GetVdbe(pParse);
if( v==0 || NEVER(pTab==0) ){
return;
}
if( !IsOrdinaryTable(pTab) ){
/* Do not gather statistics on views or virtual tables */
return;
}
if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){
/* Do not gather statistics on system tables */
return;
}
|
| ︙ | ︙ | |||
112047 112048 112049 112050 112051 112052 112053 | int regArgs; if( pParse->nErr ) goto attach_end; memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( | | | | > | 112661 112662 112663 112664 112665 112666 112667 112668 112669 112670 112671 112672 112673 112674 112675 112676 112677 112678 112679 112680 112681 112682 112683 112684 112685 112686 |
int regArgs;
if( pParse->nErr ) goto attach_end;
memset(&sName, 0, sizeof(NameContext));
sName.pParse = pParse;
if(
SQLITE_OK!=resolveAttachExpr(&sName, pFilename) ||
SQLITE_OK!=resolveAttachExpr(&sName, pDbname) ||
SQLITE_OK!=resolveAttachExpr(&sName, pKey)
){
goto attach_end;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pAuthArg ){
char *zAuthArg;
if( pAuthArg->op==TK_STRING ){
assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
zAuthArg = pAuthArg->u.zToken;
}else{
zAuthArg = 0;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
if(rc!=SQLITE_OK ){
goto attach_end;
|
| ︙ | ︙ | |||
112742 112743 112744 112745 112746 112747 112748 |
if( v ){
if( pParse->bReturning ){
Returning *pReturning = pParse->u1.pReturning;
int addrRewind;
int i;
int reg;
| > > > > | | | | | | | | | | | > | 113357 113358 113359 113360 113361 113362 113363 113364 113365 113366 113367 113368 113369 113370 113371 113372 113373 113374 113375 113376 113377 113378 113379 113380 113381 113382 113383 113384 113385 113386 |
if( v ){
if( pParse->bReturning ){
Returning *pReturning = pParse->u1.pReturning;
int addrRewind;
int i;
int reg;
if( pReturning->nRetCol==0 ){
assert( CORRUPT_DB );
}else{
sqlite3VdbeAddOp0(v, OP_FkCheck);
addrRewind =
sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
VdbeCoverage(v);
reg = pReturning->iRetReg;
for(i=0; i<pReturning->nRetCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
}
sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrRewind);
}
}
sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
if( pParse->nTableLock>0 && db->init.busy==0 ){
sqlite3UserAuthInit(db);
if( db->auth.authLevel<UAUTH_User ){
|
| ︙ | ︙ | |||
112833 112834 112835 112836 112837 112838 112839 |
sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
}
}
}
if( pParse->bReturning ){
Returning *pRet = pParse->u1.pReturning;
| > > > | > | 113453 113454 113455 113456 113457 113458 113459 113460 113461 113462 113463 113464 113465 113466 113467 113468 113469 113470 113471 |
sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
}
}
}
if( pParse->bReturning ){
Returning *pRet = pParse->u1.pReturning;
if( pRet->nRetCol==0 ){
assert( CORRUPT_DB );
}else{
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeGoto(v, 1);
}
}
|
| ︙ | ︙ | |||
112951 112952 112953 112954 112955 112956 112957 |
}else{
return 0;
}
}
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( i==1 ){
| | | | | | | | | | | | 113575 113576 113577 113578 113579 113580 113581 113582 113583 113584 113585 113586 113587 113588 113589 113590 113591 113592 113593 113594 113595 113596 113597 113598 113599 113600 113601 113602 113603 113604 113605 113606 113607 113608 113609 113610 113611 113612 113613 113614 113615 113616 113617 113618 113619 113620 113621 |
}else{
return 0;
}
}
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( i==1 ){
if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0
){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
LEGACY_TEMP_SCHEMA_TABLE);
}
}else{
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
LEGACY_SCHEMA_TABLE);
}
}
}
}else{
/* Match against TEMP first */
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
if( p ) return p;
/* The main database is second */
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
if( p ) return p;
/* Attached databases are in order of attachment */
for(i=2; i<db->nDb; i++){
assert( sqlite3SchemaMutexHeld(db, i, 0) );
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p ) break;
}
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE);
}else if( sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
LEGACY_TEMP_SCHEMA_TABLE);
}
}
}
return p;
}
/*
|
| ︙ | ︙ | |||
113078 113079 113080 113081 113082 113083 113084 113085 113086 113087 113088 113089 113090 113091 |
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
zDb = p->zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
| > > > > > > > > > > > > > > > > | 113702 113703 113704 113705 113706 113707 113708 113709 113710 113711 113712 113713 113714 113715 113716 113717 113718 113719 113720 113721 113722 113723 113724 113725 113726 113727 113728 113729 113730 113731 |
int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
zDb = p->zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
/*
** Return the preferred table name for system tables. Translate legacy
** names into the new preferred names, as appropriate.
*/
SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char *zName){
if( sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 ){
return PREFERRED_SCHEMA_TABLE;
}
if( sqlite3StrICmp(zName+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
return PREFERRED_TEMP_SCHEMA_TABLE;
}
}
return zName;
}
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
|
| ︙ | ︙ | |||
113255 113256 113257 113258 113259 113260 113261 |
SQLITE_PRIVATE void sqlite3ColumnSetExpr(
Parse *pParse, /* Parsing context */
Table *pTab, /* The table containing the column */
Column *pCol, /* The column to receive the new DEFAULT expression */
Expr *pExpr /* The new default expression */
){
ExprList *pList;
| | | | | | 113895 113896 113897 113898 113899 113900 113901 113902 113903 113904 113905 113906 113907 113908 113909 113910 113911 113912 113913 113914 113915 113916 113917 113918 113919 113920 113921 113922 113923 113924 113925 113926 113927 113928 113929 113930 113931 113932 113933 113934 113935 113936 113937 113938 113939 113940 113941 113942 113943 113944 113945 |
SQLITE_PRIVATE void sqlite3ColumnSetExpr(
Parse *pParse, /* Parsing context */
Table *pTab, /* The table containing the column */
Column *pCol, /* The column to receive the new DEFAULT expression */
Expr *pExpr /* The new default expression */
){
ExprList *pList;
assert( IsOrdinaryTable(pTab) );
pList = pTab->u.tab.pDfltList;
if( pCol->iDflt==0
|| NEVER(pList==0)
|| NEVER(pList->nExpr<pCol->iDflt)
){
pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
pTab->u.tab.pDfltList = sqlite3ExprListAppend(pParse, pList, pExpr);
}else{
sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
pList->a[pCol->iDflt-1].pExpr = pExpr;
}
}
/*
** Return the expression associated with a column. The expression might be
** the DEFAULT clause or the AS clause of a generated column.
** Return NULL if the column has no associated expression.
*/
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
if( pCol->iDflt==0 ) return 0;
if( NEVER(!IsOrdinaryTable(pTab)) ) return 0;
if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
}
/*
** Set the collating sequence name for a column.
*/
SQLITE_PRIVATE void sqlite3ColumnSetColl(
sqlite3 *db,
Column *pCol,
const char *zColl
){
i64 nColl;
i64 n;
char *zNew;
assert( zColl!=0 );
n = sqlite3Strlen30(pCol->zCnName) + 1;
if( pCol->colFlags & COLFLAG_HASTYPE ){
n += sqlite3Strlen30(pCol->zCnName+n) + 1;
}
nColl = sqlite3Strlen30(zColl) + 1;
|
| ︙ | ︙ | |||
113335 113336 113337 113338 113339 113340 113341 |
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
sqlite3DbFree(db, pCol->zCnName);
}
sqlite3DbFree(db, pTable->aCol);
| | | | 113975 113976 113977 113978 113979 113980 113981 113982 113983 113984 113985 113986 113987 113988 113989 113990 113991 113992 113993 113994 113995 |
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
sqlite3DbFree(db, pCol->zCnName);
}
sqlite3DbFree(db, pTable->aCol);
if( IsOrdinaryTable(pTable) ){
sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
}
if( db==0 || db->pnBytesFreed==0 ){
pTable->aCol = 0;
pTable->nCol = 0;
if( IsOrdinaryTable(pTable) ){
pTable->u.tab.pDfltList = 0;
}
}
}
}
/*
|
| ︙ | ︙ | |||
113477 113478 113479 113480 113481 113482 113483 |
/*
** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
| | | 114117 114118 114119 114120 114121 114122 114123 114124 114125 114126 114127 114128 114129 114130 114131 |
/*
** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
}
/*
|
| ︙ | ︙ | |||
114096 114097 114098 114099 114100 114101 114102 |
affinity = sqlite3StdTypeAffinity[i];
if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
break;
}
}
}
| | | | 114736 114737 114738 114739 114740 114741 114742 114743 114744 114745 114746 114747 114748 114749 114750 114751 114752 114753 114754 114755 114756 114757 114758 114759 114760 114761 114762 114763 114764 |
affinity = sqlite3StdTypeAffinity[i];
if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
break;
}
}
}
z = sqlite3DbMallocRaw(db, (i64)sName.n + 1 + (i64)sType.n + (sType.n>0) );
if( z==0 ) return;
if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, &sName);
memcpy(z, sName.z, sName.n);
z[sName.n] = 0;
sqlite3Dequote(z);
hName = sqlite3StrIHash(z);
for(i=0; i<p->nCol; i++){
if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlite3DbFree(db, z);
return;
}
}
aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
if( aNew==0 ){
sqlite3DbFree(db, z);
return;
}
p->aCol = aNew;
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
|
| ︙ | ︙ | |||
114408 114409 114410 114411 114412 114413 114414 |
}else{
nTerm = pList->nExpr;
for(i=0; i<nTerm; i++){
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
assert( pCExpr!=0 );
sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
| | > > | 115048 115049 115050 115051 115052 115053 115054 115055 115056 115057 115058 115059 115060 115061 115062 115063 115064 |
}else{
nTerm = pList->nExpr;
for(i=0; i<nTerm; i++){
Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr);
assert( pCExpr!=0 );
sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
const char *zCName;
assert( !ExprHasProperty(pCExpr, EP_IntValue) );
zCName = pCExpr->u.zToken;
for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
pCol = &pTab->aCol[iCol];
makeColumnPartOfPrimaryKey(pParse, pCol);
break;
}
}
|
| ︙ | ︙ | |||
114780 114781 114782 114783 114784 114785 114786 |
/* Return true if column number x is any of the first nCol entries of aiCol[].
** This is used to determine if the column number x appears in any of the
** first nCol entries of an index.
*/
static int hasColumn(const i16 *aiCol, int nCol, int x){
while( nCol-- > 0 ){
| < | 115422 115423 115424 115425 115426 115427 115428 115429 115430 115431 115432 115433 115434 115435 |
/* Return true if column number x is any of the first nCol entries of aiCol[].
** This is used to determine if the column number x appears in any of the
** first nCol entries of an index.
*/
static int hasColumn(const i16 *aiCol, int nCol, int x){
while( nCol-- > 0 ){
if( x==*(aiCol++) ){
return 1;
}
}
return 0;
}
|
| ︙ | ︙ | |||
115055 115056 115057 115058 115059 115060 115061 115062 115063 115064 115065 115066 115067 115068 | if( pMod==0 ) return 0; if( pMod->pModule->iVersion<3 ) return 0; if( pMod->pModule->xShadowName==0 ) return 0; return pMod->pModule->xShadowName(zName+nName+1); } #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Return true if zName is a shadow table name in the current database ** connection. ** ** zName is temporarily modified while this routine is running, but is ** restored to its original value prior to this routine returning. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 115696 115697 115698 115699 115700 115701 115702 115703 115704 115705 115706 115707 115708 115709 115710 115711 115712 115713 115714 115715 115716 115717 115718 115719 115720 115721 115722 115723 115724 115725 115726 115727 115728 115729 115730 115731 115732 115733 115734 115735 115736 115737 115738 115739 115740 115741 115742 115743 115744 |
if( pMod==0 ) return 0;
if( pMod->pModule->iVersion<3 ) return 0;
if( pMod->pModule->xShadowName==0 ) return 0;
return pMod->pModule->xShadowName(zName+nName+1);
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Table pTab is a virtual table. If it the virtual table implementation
** exists and has an xShadowName method, then loop over all other ordinary
** tables within the same schema looking for shadow tables of pTab, and mark
** any shadow tables seen using the TF_Shadow flag.
*/
SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3 *db, Table *pTab){
int nName; /* Length of pTab->zName */
Module *pMod; /* Module for the virtual table */
HashElem *k; /* For looping through the symbol table */
assert( IsVirtual(pTab) );
pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
if( pMod==0 ) return;
if( NEVER(pMod->pModule==0) ) return;
if( pMod->pModule->iVersion<3 ) return;
if( pMod->pModule->xShadowName==0 ) return;
assert( pTab->zName!=0 );
nName = sqlite3Strlen30(pTab->zName);
for(k=sqliteHashFirst(&pTab->pSchema->tblHash); k; k=sqliteHashNext(k)){
Table *pOther = sqliteHashData(k);
assert( pOther->zName!=0 );
if( !IsOrdinaryTable(pOther) ) continue;
if( pOther->tabFlags & TF_Shadow ) continue;
if( sqlite3StrNICmp(pOther->zName, pTab->zName, nName)==0
&& pOther->zName[nName]=='_'
&& pMod->pModule->xShadowName(pOther->zName+nName+1)
){
pOther->tabFlags |= TF_Shadow;
}
}
}
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if zName is a shadow table name in the current database
** connection.
**
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
|
| ︙ | ︙ | |||
115156 115157 115158 115159 115160 115161 115162 |
** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.)
**
** If the root page number is 1, that means this is the sqlite_schema
** table itself. So mark it read-only.
*/
if( db->init.busy ){
| | | 115832 115833 115834 115835 115836 115837 115838 115839 115840 115841 115842 115843 115844 115845 115846 |
** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.)
**
** If the root page number is 1, that means this is the sqlite_schema
** table itself. So mark it read-only.
*/
if( db->init.busy ){
if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){
sqlite3ErrorMsg(pParse, "");
return;
}
p->tnum = db->init.newTnum;
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
|
| ︙ | ︙ | |||
115383 115384 115385 115386 115387 115388 115389 |
}
/* A slot for the record has already been allocated in the
** schema table. We just need to update that slot with all
** the information we've collected.
*/
sqlite3NestedParse(pParse,
| | | 116059 116060 116061 116062 116063 116064 116065 116066 116067 116068 116069 116070 116071 116072 116073 |
}
/* A slot for the record has already been allocated in the
** schema table. We just need to update that slot with all
** the information we've collected.
*/
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
" WHERE rowid=#%d",
db->aDb[iDb].zDbSName,
zType,
p->zName,
p->zName,
pParse->regRoot,
|
| ︙ | ︙ | |||
115569 115570 115571 115572 115573 115574 115575 | #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth; /* Saved xAuth pointer */ #endif assert( pTable ); #ifndef SQLITE_OMIT_VIRTUALTABLE | > | | | < | < | 116245 116246 116247 116248 116249 116250 116251 116252 116253 116254 116255 116256 116257 116258 116259 116260 116261 116262 116263 116264 |
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Saved xAuth pointer */
#endif
assert( pTable );
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTable) ){
db->nSchemaLock++;
rc = sqlite3VtabCallConnect(pParse, pTable);
db->nSchemaLock--;
return rc;
}
#endif
#ifndef SQLITE_OMIT_VIEW
/* A positive nCol means the columns names for this view are
** already known.
*/
if( pTable->nCol>0 ) return 0;
|
| ︙ | ︙ | |||
115763 115764 115765 115766 115767 115768 115769 | ** reflect this. ** ** The "#NNN" in the SQL is a special constant that means whatever value ** is in register NNN. See grammar rules associated with the TK_REGISTER ** token for additional information. */ sqlite3NestedParse(pParse, | | | 116438 116439 116440 116441 116442 116443 116444 116445 116446 116447 116448 116449 116450 116451 116452 |
** reflect this.
**
** The "#NNN" in the SQL is a special constant that means whatever value
** is in register NNN. See grammar rules associated with the TK_REGISTER
** token for additional information.
*/
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
/*
|
| ︙ | ︙ | |||
115898 115899 115900 115901 115902 115903 115904 | ** table. The program name loops through the schema table and deletes ** every row that refers to a table of the same name as the one being ** dropped. Triggers are handled separately because a trigger can be ** created in the temp database that refers to a table in another ** database. */ sqlite3NestedParse(pParse, | | | 116573 116574 116575 116576 116577 116578 116579 116580 116581 116582 116583 116584 116585 116586 116587 |
** table. The program name loops through the schema table and deletes
** every row that refers to a table of the same name as the one being
** dropped. Triggers are handled separately because a trigger can be
** created in the temp database that refers to a table in another
** database.
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE
" WHERE tbl_name=%Q and type!='trigger'",
pDb->zDbSName, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
/* Remove the table entry from SQLite's internal schema and modify
|
| ︙ | ︙ | |||
115945 115946 115947 115948 115949 115950 115951 115952 115953 115954 115955 115956 115957 115958 |
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
return 1;
}
if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
return 1;
}
return 0;
}
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
| > > > | 116620 116621 116622 116623 116624 116625 116626 116627 116628 116629 116630 116631 116632 116633 116634 116635 116636 |
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
return 1;
}
if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
return 1;
}
if( pTab->tabFlags & TF_Eponymous ){
return 1;
}
return 0;
}
/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
|
| ︙ | ︙ | |||
116085 116086 116087 116088 116089 116090 116091 |
int flags /* Conflict resolution algorithms. */
){
sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
FKey *pFKey = 0;
FKey *pNextTo;
Table *p = pParse->pNewTable;
| | | 116763 116764 116765 116766 116767 116768 116769 116770 116771 116772 116773 116774 116775 116776 116777 |
int flags /* Conflict resolution algorithms. */
){
sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
FKey *pFKey = 0;
FKey *pNextTo;
Table *p = pParse->pNewTable;
i64 nByte;
int i;
int nCol;
char *z;
assert( pTo!=0 );
if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
if( pFromCol==0 ){
|
| ︙ | ︙ | |||
116121 116122 116123 116124 116125 116126 116127 116128 116129 116130 116131 116132 116133 116134 |
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
if( pFKey==0 ){
goto fk_end;
}
pFKey->pFrom = p;
pFKey->pNextFrom = p->u.tab.pFKey;
z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, (void*)z, pTo);
}
memcpy(z, pTo->z, pTo->n);
| > | 116799 116800 116801 116802 116803 116804 116805 116806 116807 116808 116809 116810 116811 116812 116813 |
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
if( pFKey==0 ){
goto fk_end;
}
pFKey->pFrom = p;
assert( IsOrdinaryTable(p) );
pFKey->pNextFrom = p->u.tab.pFKey;
z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, (void*)z, pTo);
}
memcpy(z, pTo->z, pTo->n);
|
| ︙ | ︙ | |||
116186 116187 116188 116189 116190 116191 116192 |
assert( pNextTo->pPrevTo==0 );
pFKey->pNextTo = pNextTo;
pNextTo->pPrevTo = pFKey;
}
/* Link the foreign key to the table as the last step.
*/
| | | 116865 116866 116867 116868 116869 116870 116871 116872 116873 116874 116875 116876 116877 116878 116879 |
assert( pNextTo->pPrevTo==0 );
pFKey->pNextTo = pNextTo;
pNextTo->pPrevTo = pFKey;
}
/* Link the foreign key to the table as the last step.
*/
assert( IsOrdinaryTable(p) );
p->u.tab.pFKey = pFKey;
pFKey = 0;
fk_end:
sqlite3DbFree(db, pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
sqlite3ExprListDelete(db, pFromCol);
|
| ︙ | ︙ | |||
116209 116210 116211 116212 116213 116214 116215 |
** accordingly.
*/
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 ) return;
| | | 116888 116889 116890 116891 116892 116893 116894 116895 116896 116897 116898 116899 116900 116901 116902 |
** accordingly.
*/
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 ) return;
if( NEVER(!IsOrdinaryTable(pTab)) ) return;
if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
pFKey->isDeferred = (u8)isDeferred;
#endif
}
/*
|
| ︙ | ︙ | |||
116611 116612 116613 116614 116615 116616 116617 116618 116619 116620 116621 116622 116623 116624 |
/* Figure out how many bytes of space are required to store explicitly
** specified collation sequence names.
*/
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
assert( pExpr!=0 );
if( pExpr->op==TK_COLLATE ){
nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
}
}
/*
** Allocate the index structure.
*/
| > | 117290 117291 117292 117293 117294 117295 117296 117297 117298 117299 117300 117301 117302 117303 117304 |
/* Figure out how many bytes of space are required to store explicitly
** specified collation sequence names.
*/
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
assert( pExpr!=0 );
if( pExpr->op==TK_COLLATE ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
}
}
/*
** Allocate the index structure.
*/
|
| ︙ | ︙ | |||
116706 116707 116708 116709 116710 116711 116712 116713 116714 116715 116716 116717 116718 116719 |
}
}
pIndex->aiColumn[i] = (i16)j;
}
zColl = 0;
if( pListItem->pExpr->op==TK_COLLATE ){
int nColl;
zColl = pListItem->pExpr->u.zToken;
nColl = sqlite3Strlen30(zColl) + 1;
assert( nExtra>=nColl );
memcpy(zExtra, zColl, nColl);
zColl = zExtra;
zExtra += nColl;
nExtra -= nColl;
| > | 117386 117387 117388 117389 117390 117391 117392 117393 117394 117395 117396 117397 117398 117399 117400 |
}
}
pIndex->aiColumn[i] = (i16)j;
}
zColl = 0;
if( pListItem->pExpr->op==TK_COLLATE ){
int nColl;
assert( !ExprHasProperty(pListItem->pExpr, EP_IntValue) );
zColl = pListItem->pExpr->u.zToken;
nColl = sqlite3Strlen30(zColl) + 1;
assert( nExtra>=nColl );
memcpy(zExtra, zColl, nColl);
zColl = zExtra;
zExtra += nColl;
nExtra -= nColl;
|
| ︙ | ︙ | |||
116912 116913 116914 116915 116916 116917 116918 |
/* zStmt = sqlite3MPrintf(""); */
zStmt = 0;
}
/* Add an entry in sqlite_schema for this index
*/
sqlite3NestedParse(pParse,
| | | | | | | | | 117593 117594 117595 117596 117597 117598 117599 117600 117601 117602 117603 117604 117605 117606 117607 117608 117609 117610 117611 117612 117613 |
/* zStmt = sqlite3MPrintf(""); */
zStmt = 0;
}
/* Add an entry in sqlite_schema for this index
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zDbSName,
pIndex->zName,
pTab->zName,
iMem,
zStmt
);
sqlite3DbFree(db, zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire
** to invalidate all pre-compiled statements.
*/
if( pTblName ){
sqlite3RefillIndex(pParse, pIndex, iMem);
|
| ︙ | ︙ | |||
117098 117099 117100 117101 117102 117103 117104 |
#endif
/* Generate code to remove the index and from the schema table */
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
| | | 117779 117780 117781 117782 117783 117784 117785 117786 117787 117788 117789 117790 117791 117792 117793 |
#endif
/* Generate code to remove the index and from the schema table */
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
db->aDb[iDb].zDbSName, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
destroyRootPage(pParse, pIndex->tnum, iDb);
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
}
|
| ︙ | ︙ | |||
117466 117467 117468 117469 117470 117471 117472 |
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
pItem->pSelect = pSubquery;
pItem->pOn = pOn;
pItem->pUsing = pUsing;
return p;
| | | 118147 118148 118149 118150 118151 118152 118153 118154 118155 118156 118157 118158 118159 118160 118161 |
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
pItem->pSelect = pSubquery;
pItem->pOn = pOn;
pItem->pUsing = pUsing;
return p;
append_from_error:
assert( p==0 );
sqlite3ExprDelete(db, pOn);
sqlite3IdListDelete(db, pUsing);
sqlite3SelectDelete(db, pSubquery);
return 0;
}
|
| ︙ | ︙ | |||
117494 117495 117496 117497 117498 117499 117500 117501 117502 117503 117504 117505 117506 117507 |
if( pIndexedBy->n==1 && !pIndexedBy->z ){
/* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->fg.notIndexed = 1;
}else{
pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
pItem->fg.isIndexedBy = 1;
}
}
}
/*
** Append the contents of SrcList p2 to SrcList p1 and return the resulting
** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2
| > | 118175 118176 118177 118178 118179 118180 118181 118182 118183 118184 118185 118186 118187 118188 118189 |
if( pIndexedBy->n==1 && !pIndexedBy->z ){
/* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->fg.notIndexed = 1;
}else{
pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
pItem->fg.isIndexedBy = 1;
assert( pItem->fg.isCte==0 ); /* No collision on union u2 */
}
}
}
/*
** Append the contents of SrcList p2 to SrcList p1 and return the resulting
** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2
|
| ︙ | ︙ | |||
118474 118475 118476 118477 118478 118479 118480 118481 118482 118483 118484 118485 118486 118487 |
*/
SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
FuncDef *p;
for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
if( sqlite3StrICmp(p->zName, zFunc)==0 ){
return p;
}
}
return 0;
}
| > | 119156 119157 119158 119159 119160 119161 119162 119163 119164 119165 119166 119167 119168 119169 119170 |
*/
SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
FuncDef *p;
for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
if( sqlite3StrICmp(p->zName, zFunc)==0 ){
return p;
}
}
return 0;
}
|
| ︙ | ︙ | |||
118495 118496 118497 118498 118499 118500 118501 118502 118503 118504 118505 118506 118507 118508 |
int i;
for(i=0; i<nDef; i++){
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
pOther->pNext = &aDef[i];
}else{
aDef[i].pNext = 0;
| > | 119178 119179 119180 119181 119182 119183 119184 119185 119186 119187 119188 119189 119190 119191 119192 |
int i;
for(i=0; i<nDef; i++){
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );
pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
pOther->pNext = &aDef[i];
}else{
aDef[i].pNext = 0;
|
| ︙ | ︙ | |||
118719 118720 118721 118722 118723 118724 118725 118726 118727 118728 118729 118730 118731 118732 |
pTab->nTabRef++;
if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
pTab = 0;
}
}
return pTab;
}
/* Return true if table pTab is read-only.
**
** A table is read-only if any of the following are true:
**
** 1) It is a virtual table and no implementation of the xUpdate method
** has been provided
| > > > > > > > > > > | 119403 119404 119405 119406 119407 119408 119409 119410 119411 119412 119413 119414 119415 119416 119417 119418 119419 119420 119421 119422 119423 119424 119425 119426 |
pTab->nTabRef++;
if( pItem->fg.isIndexedBy && sqlite3IndexedByLookup(pParse, pItem) ){
pTab = 0;
}
}
return pTab;
}
/* Generate byte-code that will report the number of rows modified
** by a DELETE, INSERT, or UPDATE statement.
*/
SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
sqlite3VdbeAddOp0(v, OP_FkCheck);
sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
}
/* Return true if table pTab is read-only.
**
** A table is read-only if any of the following are true:
**
** 1) It is a virtual table and no implementation of the xUpdate method
** has been provided
|
| ︙ | ︙ | |||
118886 118887 118888 118889 118890 118891 118892 118893 118894 118895 118896 118897 118898 118899 |
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
pSrc->a[0].u2.pIBIndex = 0;
pSrc->a[0].fg.isIndexedBy = 0;
sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
}else if( pSrc->a[0].fg.isCte ){
pSrc->a[0].u2.pCteUse->nUse++;
}
| > | 119580 119581 119582 119583 119584 119585 119586 119587 119588 119589 119590 119591 119592 119593 119594 |
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
assert( pSrc->a[0].fg.isCte==0 );
pSrc->a[0].u2.pIBIndex = 0;
pSrc->a[0].fg.isIndexedBy = 0;
sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
}else if( pSrc->a[0].fg.isCte ){
pSrc->a[0].u2.pCteUse->nUse++;
}
|
| ︙ | ︙ | |||
119294 119295 119296 119297 119298 119299 119300 |
}
/* Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( memCnt ){
| < < | | 119989 119990 119991 119992 119993 119994 119995 119996 119997 119998 119999 120000 120001 120002 120003 |
}
/* Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( memCnt ){
sqlite3CodeChangeCount(v, memCnt, "rows deleted");
}
delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprDelete(db, pWhere);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
|
| ︙ | ︙ | |||
121470 121471 121472 121473 121474 121475 121476 |
assert( argc==1 || argc==2 );
(void)argc; /* Suppress unused parameter warning */
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
/* pGCC is always non-NULL since groupConcatStep() will have always
** run frist to initialize it */
if( ALWAYS(pGCC) ){
| > > > > | | 122163 122164 122165 122166 122167 122168 122169 122170 122171 122172 122173 122174 122175 122176 122177 122178 122179 122180 122181 |
assert( argc==1 || argc==2 );
(void)argc; /* Suppress unused parameter warning */
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pGCC = (GroupConcatCtx*)sqlite3_aggregate_context(context, sizeof(*pGCC));
/* pGCC is always non-NULL since groupConcatStep() will have always
** run frist to initialize it */
if( ALWAYS(pGCC) ){
int nVS;
/* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]);
nVS = sqlite3_value_bytes(argv[0]);
pGCC->nAccum -= 1;
if( pGCC->pnSepLengths!=0 ){
assert(pGCC->nAccum >= 0);
if( pGCC->nAccum>0 ){
nVS += *pGCC->pnSepLengths;
memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1,
(pGCC->nAccum-1)*sizeof(int));
|
| ︙ | ︙ | |||
121585 121586 121587 121588 121589 121590 121591 121592 121593 121594 |
** false.
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
int nExpr;
assert( pExpr!=0 );
assert( pExpr->op==TK_FUNCTION );
if( !pExpr->x.pList ){
return 0;
}
| > < > | 122282 122283 122284 122285 122286 122287 122288 122289 122290 122291 122292 122293 122294 122295 122296 122297 122298 122299 122300 122301 |
** false.
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
int nExpr;
assert( pExpr!=0 );
assert( pExpr->op==TK_FUNCTION );
assert( ExprUseXList(pExpr) );
if( !pExpr->x.pList ){
return 0;
}
nExpr = pExpr->x.pList->nExpr;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
if( pDef==0 ) return 0;
#endif
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
|
| ︙ | ︙ | |||
121613 121614 121615 121616 121617 121618 121619 121620 121621 121622 121623 121624 121625 121626 |
if( nExpr<3 ){
aWc[3] = 0;
}else{
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
char *zEscape;
if( pEscape->op!=TK_STRING ) return 0;
zEscape = pEscape->u.zToken;
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
if( zEscape[0]==aWc[0] ) return 0;
if( zEscape[0]==aWc[1] ) return 0;
aWc[3] = zEscape[0];
}
| > | 122311 122312 122313 122314 122315 122316 122317 122318 122319 122320 122321 122322 122323 122324 122325 |
if( nExpr<3 ){
aWc[3] = 0;
}else{
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
char *zEscape;
if( pEscape->op!=TK_STRING ) return 0;
assert( !ExprHasProperty(pEscape, EP_IntValue) );
zEscape = pEscape->u.zToken;
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
if( zEscape[0]==aWc[0] ) return 0;
if( zEscape[0]==aWc[1] ) return 0;
aWc[3] = zEscape[0];
}
|
| ︙ | ︙ | |||
121994 121995 121996 121997 121998 121999 122000 122001 122002 122003 122004 122005 122006 122007 |
int i;
FuncDef *p;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
printf("FUNC-HASH %02d:", i);
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
int n = sqlite3Strlen30(p->zName);
int h = p->zName[0] + n;
printf(" %s(%d)", p->zName, h);
}
printf("\n");
}
}
#endif
}
| > | 122693 122694 122695 122696 122697 122698 122699 122700 122701 122702 122703 122704 122705 122706 122707 |
int i;
FuncDef *p;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
printf("FUNC-HASH %02d:", i);
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
int n = sqlite3Strlen30(p->zName);
int h = p->zName[0] + n;
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
printf(" %s(%d)", p->zName, h);
}
printf("\n");
}
}
#endif
}
|
| ︙ | ︙ | |||
122516 122517 122518 122519 122520 122521 122522 122523 122524 122525 122526 122527 122528 122529 |
sqlite3 *db, /* The database connection */
Table *pTab, /* The table whose column is desired */
int iCursor, /* The open cursor on the table */
i16 iCol /* The column that is wanted */
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
return pExpr;
}
| > | 123216 123217 123218 123219 123220 123221 123222 123223 123224 123225 123226 123227 123228 123229 123230 |
sqlite3 *db, /* The database connection */
Table *pTab, /* The table whose column is desired */
int iCursor, /* The open cursor on the table */
i16 iCol /* The column that is wanted */
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
return pExpr;
}
|
| ︙ | ︙ | |||
122726 122727 122728 122729 122730 122731 122732 |
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
** the table from the database. Triggers are disabled while running this
** DELETE, but foreign key actions are not.
*/
SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
sqlite3 *db = pParse->db;
| | < | | 123427 123428 123429 123430 123431 123432 123433 123434 123435 123436 123437 123438 123439 123440 123441 123442 123443 123444 123445 123446 |
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
** the table from the database. Triggers are disabled while running this
** DELETE, but foreign key actions are not.
*/
SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
sqlite3 *db = pParse->db;
if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
int iSkip = 0;
Vdbe *v = sqlite3GetVdbe(pParse);
assert( v ); /* VDBE has already been allocated */
assert( IsOrdinaryTable(pTab) );
if( sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table
** is the child table. If one cannot be found, return without
** generating any VDBE code. If one can be found, then jump over
** the entire DELETE if there are no outstanding deferred constraints
** when this statement is run. */
FKey *p;
|
| ︙ | ︙ | |||
122896 122897 122898 122899 122900 122901 122902 122903 122904 122905 122906 122907 122908 | int isIgnoreErrors = pParse->disableTriggers; /* Exactly one of regOld and regNew should be non-zero. */ assert( (regOld==0)!=(regNew==0) ); /* If foreign-keys are disabled, this function is a no-op. */ if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ | > < | 123596 123597 123598 123599 123600 123601 123602 123603 123604 123605 123606 123607 123608 123609 123610 123611 123612 123613 123614 123615 123616 |
int isIgnoreErrors = pParse->disableTriggers;
/* Exactly one of regOld and regNew should be non-zero. */
assert( (regOld==0)!=(regNew==0) );
/* If foreign-keys are disabled, this function is a no-op. */
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
if( !IsOrdinaryTable(pTab) ) return;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
/* Loop through all the foreign key constraints for which pTab is the
** child table (the table that the foreign key definition is part of). */
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
Table *pTo; /* Parent table of foreign key pFKey */
Index *pIdx = 0; /* Index on key columns in pTo */
int *aiFree = 0;
int *aiCol;
int iCol;
int i;
|
| ︙ | ︙ | |||
123085 123086 123087 123088 123089 123090 123091 |
** row contained in table pTab.
*/
SQLITE_PRIVATE u32 sqlite3FkOldmask(
Parse *pParse, /* Parse context */
Table *pTab /* Table being modified */
){
u32 mask = 0;
| | < | 123785 123786 123787 123788 123789 123790 123791 123792 123793 123794 123795 123796 123797 123798 123799 123800 123801 |
** row contained in table pTab.
*/
SQLITE_PRIVATE u32 sqlite3FkOldmask(
Parse *pParse, /* Parse context */
Table *pTab /* Table being modified */
){
u32 mask = 0;
if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
FKey *p;
int i;
for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
}
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
Index *pIdx = 0;
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){
|
| ︙ | ︙ | |||
123139 123140 123141 123142 123143 123144 123145 |
Parse *pParse, /* Parse context */
Table *pTab, /* Table being modified */
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
int eRet = 1; /* Value to return if bHaveFK is true */
int bHaveFK = 0; /* If FK processing is required */
| | | 123838 123839 123840 123841 123842 123843 123844 123845 123846 123847 123848 123849 123850 123851 123852 |
Parse *pParse, /* Parse context */
Table *pTab, /* Table being modified */
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
int eRet = 1; /* Value to return if bHaveFK is true */
int bHaveFK = 0; /* If FK processing is required */
if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
bHaveFK = (sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
|
| ︙ | ︙ | |||
123427 123428 123429 123430 123431 123432 123433 |
** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
** hash table.
*/
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
| | | 124126 124127 124128 124129 124130 124131 124132 124133 124134 124135 124136 124137 124138 124139 124140 |
** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
** hash table.
*/
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
assert( IsOrdinaryTable(pTab) );
for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
/* Remove the FK from the fkeyHash hash table. */
if( !db || db->pnBytesFreed==0 ){
if( pFKey->pPrevTo ){
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
|
| ︙ | ︙ | |||
123748 123749 123750 123751 123752 123753 123754 | testcase( pTab->tabFlags & TF_HasVirtual ); testcase( pTab->tabFlags & TF_HasStored ); /* Before computing generated columns, first go through and make sure ** that appropriate affinity has been applied to the regular columns */ sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore); | | | | | | | | | | | | | | | | | | | > > > > > > | 124447 124448 124449 124450 124451 124452 124453 124454 124455 124456 124457 124458 124459 124460 124461 124462 124463 124464 124465 124466 124467 124468 124469 124470 124471 124472 124473 124474 124475 124476 124477 124478 124479 124480 124481 124482 124483 124484 |
testcase( pTab->tabFlags & TF_HasVirtual );
testcase( pTab->tabFlags & TF_HasStored );
/* Before computing generated columns, first go through and make sure
** that appropriate affinity has been applied to the regular columns
*/
sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
if( (pTab->tabFlags & TF_HasStored)!=0 ){
pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
if( pOp->opcode==OP_Affinity ){
/* Change the OP_Affinity argument to '@' (NONE) for all stored
** columns. '@' is the no-op affinity and those columns have not
** yet been computed. */
int ii, jj;
char *zP4 = pOp->p4.z;
assert( zP4!=0 );
assert( pOp->p4type==P4_DYNAMIC );
for(ii=jj=0; zP4[jj]; ii++){
if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
continue;
}
if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
zP4[jj] = SQLITE_AFF_NONE;
}
jj++;
}
}else if( pOp->opcode==OP_TypeCheck ){
/* If an OP_TypeCheck was generated because the table is STRICT,
** then set the P3 operand to indicate that generated columns should
** not be checked */
pOp->p3 = 1;
}
}
/* Because there can be multiple generated columns that refer to one another,
** this is a two-pass algorithm. On the first pass, mark all generated
** columns as "not available".
*/
|
| ︙ | ︙ | |||
124842 124843 124844 124845 124846 124847 124848 |
/*
** Return the number of rows inserted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( regRowCount ){
| | < < | 125547 125548 125549 125550 125551 125552 125553 125554 125555 125556 125557 125558 125559 125560 125561 |
/*
** Return the number of rows inserted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( regRowCount ){
sqlite3CodeChangeCount(v, regRowCount, "rows inserted");
}
insert_cleanup:
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprListDelete(db, pList);
sqlite3UpsertDelete(db, pUpsert);
sqlite3SelectDelete(db, pSelect);
|
| ︙ | ︙ | |||
125686 125687 125688 125689 125690 125691 125692 125693 125694 125695 125696 125697 125698 125699 |
** (3) There are no secondary indexes on the table
** (4) No delete triggers need to be fired if there is a conflict
** (5) No FK constraint counters need to be updated if a conflict occurs.
**
** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
** must be explicitly deleted in order to ensure any pre-update hook
** is invoked. */
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
&& onError==OE_Replace /* Condition 1 */
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
| > | 126389 126390 126391 126392 126393 126394 126395 126396 126397 126398 126399 126400 126401 126402 126403 |
** (3) There are no secondary indexes on the table
** (4) No delete triggers need to be fired if there is a conflict
** (5) No FK constraint counters need to be updated if a conflict occurs.
**
** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
** must be explicitly deleted in order to ensure any pre-update hook
** is invoked. */
assert( IsOrdinaryTable(pTab) );
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
&& onError==OE_Replace /* Condition 1 */
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
|
| ︙ | ︙ | |||
125792 125793 125794 125795 125796 125797 125798 |
break;
}
default: {
int nConflictCk; /* Number of opcodes in conflict check logic */
assert( onError==OE_Replace );
nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
| | > | 126496 126497 126498 126499 126500 126501 126502 126503 126504 126505 126506 126507 126508 126509 126510 126511 |
break;
}
default: {
int nConflictCk; /* Number of opcodes in conflict check logic */
assert( onError==OE_Replace );
nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
assert( nConflictCk>0 || db->mallocFailed );
testcase( nConflictCk<=0 );
testcase( nConflictCk>1 );
if( regTrigCnt ){
sqlite3MultiWrite(pParse);
nReplaceTrig++;
}
if( pTrigger && isUpdate ){
sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur);
|
| ︙ | ︙ | |||
126078 126079 126080 126081 126082 126083 126084 |
Index *pIdx;
Vdbe *v;
assert( op==OP_OpenRead || op==OP_OpenWrite );
assert( op==OP_OpenWrite || p5==0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
| | | > | 126783 126784 126785 126786 126787 126788 126789 126790 126791 126792 126793 126794 126795 126796 126797 126798 126799 |
Index *pIdx;
Vdbe *v;
assert( op==OP_OpenRead || op==OP_OpenWrite );
assert( op==OP_OpenWrite || p5==0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
** variables *piDataCur and *piIdxCur set to illegal cursor numbers
** for improved error detection. */
*piDataCur = *piIdxCur = -999;
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
v = pParse->pVdbe;
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
|
| ︙ | ︙ | |||
126366 126367 126368 126369 126370 126371 126372 126373 126374 126375 126376 126377 126378 126379 126380 |
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
if( (pDestExpr==0)!=(pSrcExpr==0)
|| (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
pSrcExpr->u.zToken)!=0)
){
return 0; /* Default values must be the same for all columns */
}
}
| > > | 127072 127073 127074 127075 127076 127077 127078 127079 127080 127081 127082 127083 127084 127085 127086 127087 127088 |
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
Expr *pDestExpr = sqlite3ColumnExpr(pDest, pDestCol);
Expr *pSrcExpr = sqlite3ColumnExpr(pSrc, pSrcCol);
assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
assert( pDestExpr==0 || !ExprHasProperty(pDestExpr, EP_IntValue) );
assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
assert( pSrcExpr==0 || !ExprHasProperty(pSrcExpr, EP_IntValue) );
if( (pDestExpr==0)!=(pSrcExpr==0)
|| (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
pSrcExpr->u.zToken)!=0)
){
return 0; /* Default values must be the same for all columns */
}
}
|
| ︙ | ︙ | |||
126406 126407 126408 126409 126410 126411 126412 126413 126414 126415 126416 126417 126418 126419 |
/* Disallow the transfer optimization if the destination table constains
** any foreign key constraints. This is more restrictive than necessary.
** But the main beneficiary of the transfer optimization is the VACUUM
** command, and the VACUUM command disables foreign key constraints. So
** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
*/
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
return 0;
}
#endif
if( (db->flags & SQLITE_CountRows)!=0 ){
return 0; /* xfer opt does not play well with PRAGMA count_changes */
}
| > | 127114 127115 127116 127117 127118 127119 127120 127121 127122 127123 127124 127125 127126 127127 127128 |
/* Disallow the transfer optimization if the destination table constains
** any foreign key constraints. This is more restrictive than necessary.
** But the main beneficiary of the transfer optimization is the VACUUM
** command, and the VACUUM command disables foreign key constraints. So
** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
*/
assert( IsOrdinaryTable(pDest) );
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
return 0;
}
#endif
if( (db->flags & SQLITE_CountRows)!=0 ){
return 0; /* xfer opt does not play well with PRAGMA count_changes */
}
|
| ︙ | ︙ | |||
127087 127088 127089 127090 127091 127092 127093 127094 127095 127096 127097 127098 127099 127100 | void (*free_filename)(char*); sqlite3_file *(*database_file_object)(const char*); /* Version 3.34.0 and later */ int (*txn_state)(sqlite3*,const char*); /* Version 3.36.1 and later */ sqlite3_int64 (*changes64)(sqlite3*); sqlite3_int64 (*total_changes64)(sqlite3*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( | > > > > | 127796 127797 127798 127799 127800 127801 127802 127803 127804 127805 127806 127807 127808 127809 127810 127811 127812 127813 |
void (*free_filename)(char*);
sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */
int (*txn_state)(sqlite3*,const char*);
/* Version 3.36.1 and later */
sqlite3_int64 (*changes64)(sqlite3*);
sqlite3_int64 (*total_changes64)(sqlite3*);
/* Version 3.37.0 and later */
int (*autovacuum_pages)(sqlite3*,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*, void(*)(void*));
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
|
| ︙ | ︙ | |||
127393 127394 127395 127396 127397 127398 127399 127400 127401 127402 127403 127404 127405 127406 | #define sqlite3_filename_wal sqlite3_api->filename_wal /* Version 3.32.0 and later */ #define sqlite3_create_filename sqlite3_api->create_filename #define sqlite3_free_filename sqlite3_api->free_filename #define sqlite3_database_file_object sqlite3_api->database_file_object /* Version 3.34.0 and later */ #define sqlite3_txn_state sqlite3_api->txn_state #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > > > > | 128106 128107 128108 128109 128110 128111 128112 128113 128114 128115 128116 128117 128118 128119 128120 128121 128122 128123 128124 | #define sqlite3_filename_wal sqlite3_api->filename_wal /* Version 3.32.0 and later */ #define sqlite3_create_filename sqlite3_api->create_filename #define sqlite3_free_filename sqlite3_api->free_filename #define sqlite3_database_file_object sqlite3_api->database_file_object /* Version 3.34.0 and later */ #define sqlite3_txn_state sqlite3_api->txn_state /* Version 3.36.1 and later */ #define sqlite3_changes64 sqlite3_api->changes64 #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| ︙ | ︙ | |||
127880 127881 127882 127883 127884 127885 127886 127887 127888 127889 127890 127891 127892 127893 | sqlite3_free_filename, sqlite3_database_file_object, /* Version 3.34.0 and later */ sqlite3_txn_state, /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else | > > | 128598 128599 128600 128601 128602 128603 128604 128605 128606 128607 128608 128609 128610 128611 128612 128613 | sqlite3_free_filename, sqlite3_database_file_object, /* Version 3.34.0 and later */ sqlite3_txn_state, /* Version 3.36.1 and later */ sqlite3_changes64, sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
| ︙ | ︙ | |||
128869 128870 128871 128872 128873 128874 128875 |
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 8, 6,
/* iArg: */ 0 },
{/* zName: */ "table_list",
/* ePragTyp: */ PragTyp_TABLE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
/* ColNames: */ 15, 6,
| | | 129589 129590 129591 129592 129593 129594 129595 129596 129597 129598 129599 129600 129601 129602 129603 |
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 8, 6,
/* iArg: */ 0 },
{/* zName: */ "table_list",
/* ePragTyp: */ PragTyp_TABLE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
/* ColNames: */ 15, 6,
/* iArg: */ 0 },
{/* zName: */ "table_xinfo",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 8, 7,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
| ︙ | ︙ | |||
129398 129399 129400 129401 129402 129403 129404 |
pParse->nErr++;
pParse->rc = rc;
goto pragma_out;
}
/* Locate the pragma in the lookup table */
pPragma = pragmaLocate(zLeft);
| | > > > > | 130118 130119 130120 130121 130122 130123 130124 130125 130126 130127 130128 130129 130130 130131 130132 130133 130134 130135 130136 |
pParse->nErr++;
pParse->rc = rc;
goto pragma_out;
}
/* Locate the pragma in the lookup table */
pPragma = pragmaLocate(zLeft);
if( pPragma==0 ){
/* IMP: R-43042-22504 No error messages are generated if an
** unknown pragma is issued. */
goto pragma_out;
}
/* Make sure the database schema is loaded if the pragma requires that */
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
}
/* Register the result column names for pragmas that return results */
|
| ︙ | ︙ | |||
130048 130049 130050 130051 130052 130053 130054 130055 130056 130057 130058 130059 130060 130061 |
#endif
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;
}else{
db->flags &= ~mask;
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
}
/* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
sqlite3VdbeAddOp0(v, OP_Expire);
| > > > > > > > > | 130772 130773 130774 130775 130776 130777 130778 130779 130780 130781 130782 130783 130784 130785 130786 130787 130788 130789 130790 130791 130792 130793 |
#endif
if( sqlite3GetBoolean(zRight, 0) ){
db->flags |= mask;
}else{
db->flags &= ~mask;
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
if( (mask & SQLITE_WriteSchema)!=0
&& sqlite3_stricmp(zRight, "reset")==0
){
/* IMP: R-60817-01178 If the argument is "RESET" then schema
** writing is disabled (as with "PRAGMA writable_schema=OFF") and,
** in addition, the schema is reloaded. */
sqlite3ResetAllSchemasOfConnection(db);
}
}
/* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
sqlite3VdbeAddOp0(v, OP_Expire);
|
| ︙ | ︙ | |||
130088 130089 130090 130091 130092 130093 130094 130095 130096 130097 130098 130099 130100 130101 130102 130103 130104 130105 130106 130107 130108 130109 130110 130111 130112 130113 130114 |
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 7;
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
int isHidden = 0;
if( pCol->colFlags & COLFLAG_NOINSERT ){
if( pPragma->iArg==0 ){
nHidden++;
continue;
}
if( pCol->colFlags & COLFLAG_VIRTUAL ){
isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */
}else if( pCol->colFlags & COLFLAG_STORED ){
isHidden = 3; /* GENERATED ALWAYS AS ... STORED */
}else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
isHidden = 1; /* HIDDEN */
}
}
if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
k = 0;
}else if( pPk==0 ){
k = 1;
}else{
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
| > | | > | | < | 130820 130821 130822 130823 130824 130825 130826 130827 130828 130829 130830 130831 130832 130833 130834 130835 130836 130837 130838 130839 130840 130841 130842 130843 130844 130845 130846 130847 130848 130849 130850 130851 130852 130853 130854 130855 130856 130857 130858 130859 130860 130861 130862 130863 130864 |
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 7;
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
int isHidden = 0;
const Expr *pColExpr;
if( pCol->colFlags & COLFLAG_NOINSERT ){
if( pPragma->iArg==0 ){
nHidden++;
continue;
}
if( pCol->colFlags & COLFLAG_VIRTUAL ){
isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */
}else if( pCol->colFlags & COLFLAG_STORED ){
isHidden = 3; /* GENERATED ALWAYS AS ... STORED */
}else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
isHidden = 1; /* HIDDEN */
}
}
if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
k = 0;
}else if( pPk==0 ){
k = 1;
}else{
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
pColExpr = sqlite3ColumnExpr(pTab,pCol);
assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 );
assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue)
|| isHidden>=2 );
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zCnName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
(isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken,
k,
isHidden);
}
}
}
break;
|
| ︙ | ︙ | |||
130145 130146 130147 130148 130149 130150 130151 130152 130153 130154 130155 130156 130157 130158 130159 130160 130161 130162 130163 130164 130165 130166 130167 130168 |
case PragTyp_TABLE_LIST: {
int ii;
pParse->nMem = 6;
sqlite3CodeVerifyNamedSchema(pParse, zDb);
for(ii=0; ii<db->nDb; ii++){
HashElem *k;
Hash *pHash;
if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;
pHash = &db->aDb[ii].pSchema->tblHash;
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
Table *pTab = sqliteHashData(k);
const char *zType;
if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
if( IsView(pTab) ){
zType = "view";
}else if( IsVirtual(pTab) ){
zType = "virtual";
}else if( pTab->tabFlags & TF_Shadow ){
zType = "shadow";
}else{
zType = "table";
}
sqlite3VdbeMultiLoad(v, 1, "sssiii",
db->aDb[ii].zDbSName,
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 130878 130879 130880 130881 130882 130883 130884 130885 130886 130887 130888 130889 130890 130891 130892 130893 130894 130895 130896 130897 130898 130899 130900 130901 130902 130903 130904 130905 130906 130907 130908 130909 130910 130911 130912 130913 130914 130915 130916 130917 130918 130919 130920 130921 130922 130923 130924 130925 130926 130927 130928 130929 130930 130931 130932 130933 130934 130935 130936 130937 130938 130939 130940 130941 130942 130943 130944 130945 130946 130947 130948 130949 130950 130951 130952 130953 130954 130955 130956 |
case PragTyp_TABLE_LIST: {
int ii;
pParse->nMem = 6;
sqlite3CodeVerifyNamedSchema(pParse, zDb);
for(ii=0; ii<db->nDb; ii++){
HashElem *k;
Hash *pHash;
int initNCol;
if( zDb && sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;
/* Ensure that the Table.nCol field is initialized for all views
** and virtual tables. Each time we initialize a Table.nCol value
** for a table, that can potentially disrupt the hash table, so restart
** the initialization scan.
*/
pHash = &db->aDb[ii].pSchema->tblHash;
initNCol = sqliteHashCount(pHash);
while( initNCol-- ){
for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){
Table *pTab;
if( k==0 ){ initNCol = 0; break; }
pTab = sqliteHashData(k);
if( pTab->nCol==0 ){
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
if( zSql ){
sqlite3_stmt *pDummy = 0;
(void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
pHash = &db->aDb[ii].pSchema->tblHash;
break;
}
}
}
for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
Table *pTab = sqliteHashData(k);
const char *zType;
if( zRight && sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
if( IsView(pTab) ){
zType = "view";
}else if( IsVirtual(pTab) ){
zType = "virtual";
}else if( pTab->tabFlags & TF_Shadow ){
zType = "shadow";
}else{
zType = "table";
}
sqlite3VdbeMultiLoad(v, 1, "sssiii",
db->aDb[ii].zDbSName,
sqlite3PreferredTableName(pTab->zName),
zType,
pTab->nCol,
(pTab->tabFlags & TF_WithoutRowid)!=0,
(pTab->tabFlags & TF_Strict)!=0
);
}
}
}
break;
#ifdef SQLITE_DEBUG
case PragTyp_STATS: {
Index *pIdx;
HashElem *i;
pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
sqlite3VdbeMultiLoad(v, 1, "ssiii",
sqlite3PreferredTableName(pTab->zName),
0,
pTab->szTabRow,
pTab->nRowLogEst,
pTab->tabFlags);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3VdbeMultiLoad(v, 2, "siiiX",
pIdx->zName,
|
| ︙ | ︙ | |||
130301 130302 130303 130304 130305 130306 130307 130308 130309 130310 130311 130312 130313 130314 130315 130316 130317 130318 130319 |
int i;
HashElem *j;
FuncDef *p;
int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0;
pParse->nMem = 6;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
pragmaFunclistLine(v, p, 1, showInternFunc);
}
}
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
p = (FuncDef*)sqliteHashData(j);
pragmaFunclistLine(v, p, 0, showInternFunc);
}
}
break;
#ifndef SQLITE_OMIT_VIRTUALTABLE
case PragTyp_MODULE_LIST: {
| > > | 131061 131062 131063 131064 131065 131066 131067 131068 131069 131070 131071 131072 131073 131074 131075 131076 131077 131078 131079 131080 131081 |
int i;
HashElem *j;
FuncDef *p;
int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0;
pParse->nMem = 6;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
pragmaFunclistLine(v, p, 1, showInternFunc);
}
}
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
p = (FuncDef*)sqliteHashData(j);
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
pragmaFunclistLine(v, p, 0, showInternFunc);
}
}
break;
#ifndef SQLITE_OMIT_VIRTUALTABLE
case PragTyp_MODULE_LIST: {
|
| ︙ | ︙ | |||
130339 130340 130341 130342 130343 130344 130345 |
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
#ifndef SQLITE_OMIT_FOREIGN_KEY
case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
FKey *pFK;
Table *pTab;
pTab = sqlite3FindTable(db, zRight, zDb);
| | | 131101 131102 131103 131104 131105 131106 131107 131108 131109 131110 131111 131112 131113 131114 131115 |
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
#ifndef SQLITE_OMIT_FOREIGN_KEY
case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
FKey *pFK;
Table *pTab;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab && IsOrdinaryTable(pTab) ){
pFK = pTab->u.tab.pFKey;
if( pFK ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i = 0;
pParse->nMem = 8;
sqlite3CodeVerifySchema(pParse, iTabDb);
while(pFK){
|
| ︙ | ︙ | |||
130399 130400 130401 130402 130403 130404 130405 |
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
}else{
pTab = (Table*)sqliteHashData(k);
k = sqliteHashNext(k);
}
| | | | 131161 131162 131163 131164 131165 131166 131167 131168 131169 131170 131171 131172 131173 131174 131175 131176 131177 131178 131179 131180 131181 131182 131183 |
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
}else{
pTab = (Table*)sqliteHashData(k);
k = sqliteHashNext(k);
}
if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult, pTab->zName);
assert( IsOrdinaryTable(pTab) );
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
if( x==0 ){
|
| ︙ | ︙ | |||
130430 130431 130432 130433 130434 130435 130436 |
break;
}
}
assert( pParse->nErr>0 || pFK==0 );
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
| | | 131192 131193 131194 131195 131196 131197 131198 131199 131200 131201 131202 131203 131204 131205 131206 |
break;
}
}
assert( pParse->nErr>0 || pFK==0 );
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
assert( IsOrdinaryTable(pTab) );
for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0;
aiCols = 0;
if( pParent ){
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 || db->mallocFailed );
|
| ︙ | ︙ | |||
130634 130635 130636 130637 130638 130639 130640 |
Index *pIdx, *pPk;
Index *pPrior = 0;
int loopTop;
int iDataCur, iIdxCur;
int r1 = -1;
int bStrict;
| | | 131396 131397 131398 131399 131400 131401 131402 131403 131404 131405 131406 131407 131408 131409 131410 |
Index *pIdx, *pPk;
Index *pPrior = 0;
int loopTop;
int iDataCur, iIdxCur;
int r1 = -1;
int bStrict;
if( !IsOrdinaryTable(pTab) ) continue;
if( pObjTab && pObjTab!=pTab ) continue;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
/* reg[7] counts the number of entries in the table.
** reg[8+i] counts the number of entries in the i-th index
*/
|
| ︙ | ︙ | |||
130675 130676 130677 130678 130679 130680 130681 |
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
if( pCol->notNull ){
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pCol->zCnName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
| | | 131437 131438 131439 131440 131441 131442 131443 131444 131445 131446 131447 131448 131449 131450 131451 |
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
if( pCol->notNull ){
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pCol->zCnName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
if( bStrict && pCol->eCType!=COLTYPE_ANY ){
sqlite3VdbeGoto(v, doError);
}else{
integrityCheckResultRow(v);
}
sqlite3VdbeJumpHere(v, jmp2);
}
if( (pTab->tabFlags & TF_Strict)!=0
|
| ︙ | ︙ | |||
131229 131230 131231 131232 131233 131234 131235 |
**
** Configure the maximum number of rows that ANALYZE will examine
** in each index that it looks at. Return the new limit.
*/
case PragTyp_ANALYSIS_LIMIT: {
sqlite3_int64 N;
if( zRight
| | | | 131991 131992 131993 131994 131995 131996 131997 131998 131999 132000 132001 132002 132003 132004 132005 132006 132007 132008 132009 132010 |
**
** Configure the maximum number of rows that ANALYZE will examine
** in each index that it looks at. Return the new limit.
*/
case PragTyp_ANALYSIS_LIMIT: {
sqlite3_int64 N;
if( zRight
&& sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */
&& N>=0
){
db->nAnalysisLimit = (int)(N&0x7fffffff);
}
returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */
break;
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
*/
|
| ︙ | ︙ | |||
131636 131637 131638 131639 131640 131641 131642 |
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
if( db->mallocFailed ){
pData->rc = SQLITE_NOMEM_BKPT;
}else if( pData->pzErrMsg[0]!=0 ){
/* A error message has already been generated. Do not overwrite it */
| | > > > > > | | 132398 132399 132400 132401 132402 132403 132404 132405 132406 132407 132408 132409 132410 132411 132412 132413 132414 132415 132416 132417 132418 132419 132420 |
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
if( db->mallocFailed ){
pData->rc = SQLITE_NOMEM_BKPT;
}else if( pData->pzErrMsg[0]!=0 ){
/* A error message has already been generated. Do not overwrite it */
}else if( pData->mInitFlags & (INITFLAG_AlterMask) ){
static const char *azAlterType[] = {
"rename",
"drop column",
"add column"
};
*pData->pzErrMsg = sqlite3MPrintf(db,
"error in %s %s after %s: %s", azObj[0], azObj[1],
azAlterType[(pData->mInitFlags&INITFLAG_AlterMask)-1],
zExtra
);
pData->rc = SQLITE_ERROR;
}else if( db->flags & SQLITE_WriteSchema ){
pData->rc = SQLITE_CORRUPT_BKPT;
}else{
char *z;
|
| ︙ | ︙ | |||
132410 132411 132412 132413 132414 132415 132416 132417 132418 132419 132420 132421 132422 132423 |
sqlite3BtreeEnterAll(db);
do{
/* Make multiple attempts to compile the SQL, until it either succeeds
** or encounters a permanent error. A schema problem after one schema
** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
}while( rc==SQLITE_ERROR_RETRY
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
| > | 133177 133178 133179 133180 133181 133182 133183 133184 133185 133186 133187 133188 133189 133190 133191 |
sqlite3BtreeEnterAll(db);
do{
/* Make multiple attempts to compile the SQL, until it either succeeds
** or encounters a permanent error. A schema problem after one schema
** reset is considered a permanent error. */
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
if( rc==SQLITE_OK || db->mallocFailed ) break;
}while( rc==SQLITE_ERROR_RETRY
|| (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
|
| ︙ | ︙ | |||
133021 133022 133023 133024 133025 133026 133027 |
*/
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = iTable;
| | > > | | | > | 133789 133790 133791 133792 133793 133794 133795 133796 133797 133798 133799 133800 133801 133802 133803 133804 133805 133806 133807 133808 133809 |
*/
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = iTable;
if( p->op==TK_FUNCTION ){
assert( ExprUseXList(p) );
if( p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
}
sqlite3SetJoinExpr(p->pLeft, iTable);
p = p->pRight;
}
}
|
| ︙ | ︙ | |||
133047 133048 133049 133050 133051 133052 133053 |
if( ExprHasProperty(p, EP_FromJoin)
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
if( p->op==TK_COLUMN && p->iTable==iTable ){
ExprClearProperty(p, EP_CanBeNull);
}
| | > > | | | > | 133818 133819 133820 133821 133822 133823 133824 133825 133826 133827 133828 133829 133830 133831 133832 133833 133834 133835 133836 133837 133838 |
if( ExprHasProperty(p, EP_FromJoin)
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
if( p->op==TK_COLUMN && p->iTable==iTable ){
ExprClearProperty(p, EP_CanBeNull);
}
if( p->op==TK_FUNCTION ){
assert( ExprUseXList(p) );
if( p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
}
unsetJoinExpr(p->pLeft, iTable);
p = p->pRight;
}
}
|
| ︙ | ︙ | |||
133565 133566 133567 133568 133569 133570 133571 |
int i;
int nDefer = 0;
ExprList *pExtra = 0;
for(i=0; i<pEList->nExpr; i++){
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
| | | > > > > | > | 134339 134340 134341 134342 134343 134344 134345 134346 134347 134348 134349 134350 134351 134352 134353 134354 134355 134356 134357 134358 134359 134360 134361 134362 134363 134364 134365 134366 134367 134368 134369 134370 134371 134372 134373 134374 134375 134376 134377 134378 134379 134380 |
int i;
int nDefer = 0;
ExprList *pExtra = 0;
for(i=0; i<pEList->nExpr; i++){
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
Table *pTab;
if( pExpr->op==TK_COLUMN
&& pExpr->iColumn>=0
&& ALWAYS( ExprUseYTab(pExpr) )
&& (pTab = pExpr->y.pTab)!=0
&& IsOrdinaryTable(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)!=0
){
int j;
for(j=0; j<nDefer; j++){
if( pSort->aDefer[j].iCsr==pExpr->iTable ) break;
}
if( j==nDefer ){
if( nDefer==ArraySize(pSort->aDefer) ){
continue;
}else{
int nKey = 1;
int k;
Index *pPk = 0;
if( !HasRowid(pTab) ){
pPk = sqlite3PrimaryKeyIndex(pTab);
nKey = pPk->nKeyCol;
}
for(k=0; k<nKey; k++){
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
assert( ExprUseYTab(pNew) );
pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
|
| ︙ | ︙ | |||
134436 134437 134438 134439 134440 134441 134442 |
** This is not a problem, as the column type of "t1.col" is never
** used. When columnType() is called on the expression
** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
** branch below. */
break;
}
| | | 135215 135216 135217 135218 135219 135220 135221 135222 135223 135224 135225 135226 135227 135228 135229 |
** This is not a problem, as the column type of "t1.col" is never
** used. When columnType() is called on the expression
** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
** branch below. */
break;
}
assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
if( iCol<pS->pEList->nExpr
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
| ︙ | ︙ | |||
134496 134497 134498 134499 134500 134501 134502 |
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT: {
/* The expression is a sub-select. Return the declaration type and
** origin info for the single column in the result set of the SELECT
** statement.
*/
NameContext sNC;
| > > > | | < | 135275 135276 135277 135278 135279 135280 135281 135282 135283 135284 135285 135286 135287 135288 135289 135290 135291 135292 135293 |
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT: {
/* The expression is a sub-select. Return the declaration type and
** origin info for the single column in the result set of the SELECT
** statement.
*/
NameContext sNC;
Select *pS;
Expr *p;
assert( ExprUseXSelect(pExpr) );
pS = pExpr->x.pSelect;
p = pS->pEList->a[0].pExpr;
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
break;
}
#endif
|
| ︙ | ︙ | |||
134627 134628 134629 134630 134631 134632 134633 |
srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
sqlite3VdbeSetNumCols(v, pEList->nExpr);
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
| | > | 135408 135409 135410 135411 135412 135413 135414 135415 135416 135417 135418 135419 135420 135421 135422 135423 |
srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
sqlite3VdbeSetNumCols(v, pEList->nExpr);
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN
|| (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */
if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
|
| ︙ | ︙ | |||
134723 134724 134725 134726 134727 134728 134729 |
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
| | > > > | 135505 135506 135507 135508 135509 135510 135511 135512 135513 135514 135515 135516 135517 135518 135519 135520 135521 135522 |
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
if( pColExpr->op==TK_COLUMN
&& ALWAYS( ExprUseYTab(pColExpr) )
&& (pTab = pColExpr->y.pTab)!=0
){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
}else if( pColExpr->op==TK_ID ){
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
zName = pColExpr->u.zToken;
|
| ︙ | ︙ | |||
134809 134810 134811 134812 134813 134814 134815 |
assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
if( db->mallocFailed ) return;
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
| | > > > | 135594 135595 135596 135597 135598 135599 135600 135601 135602 135603 135604 135605 135606 135607 135608 135609 135610 135611 135612 135613 135614 135615 135616 135617 135618 135619 135620 135621 135622 135623 |
assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
if( db->mallocFailed ) return;
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
i64 n, m;
pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
zType = columnType(&sNC, p, 0, 0, 0);
/* pCol->szEst = ... // Column size est for SELECT tables never used */
pCol->affinity = sqlite3ExprAffinity(p);
if( zType ){
m = sqlite3Strlen30(zType);
n = sqlite3Strlen30(pCol->zCnName);
pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
if( pCol->zCnName ){
memcpy(&pCol->zCnName[n+1], zType, m+1);
pCol->colFlags |= COLFLAG_HASTYPE;
}else{
testcase( pCol->colFlags & COLFLAG_HASTYPE );
pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
}
}
if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl ){
assert( pTab->pIndex==0 );
sqlite3ColumnSetColl(db, pCol, pColl->zName);
|
| ︙ | ︙ | |||
134992 134993 134994 134995 134996 134997 134998 |
**
** Space to hold the KeyInfo structure is obtained from malloc. The calling
** function is responsible for ensuring that this structure is eventually
** freed.
*/
static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
ExprList *pOrderBy = p->pOrderBy;
| | | 135780 135781 135782 135783 135784 135785 135786 135787 135788 135789 135790 135791 135792 135793 135794 |
**
** Space to hold the KeyInfo structure is obtained from malloc. The calling
** function is responsible for ensuring that this structure is eventually
** freed.
*/
static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
ExprList *pOrderBy = p->pOrderBy;
int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
sqlite3 *db = pParse->db;
KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
if( pRet ){
int i;
for(i=0; i<nOrderBy; i++){
struct ExprList_item *pItem = &pOrderBy->a[i];
Expr *pTerm = pItem->pExpr;
|
| ︙ | ︙ | |||
135613 135614 135615 135616 135617 135618 135619 135620 135621 135622 135623 135624 135625 135626 |
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
int nCol; /* Number of columns in result set */
assert( p->pNext==0 );
nCol = p->pEList->nExpr;
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
rc = SQLITE_NOMEM_BKPT;
goto multi_select_end;
}
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
| > | 136401 136402 136403 136404 136405 136406 136407 136408 136409 136410 136411 136412 136413 136414 136415 |
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
int nCol; /* Number of columns in result set */
assert( p->pNext==0 );
assert( p->pEList!=0 );
nCol = p->pEList->nExpr;
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
rc = SQLITE_NOMEM_BKPT;
goto multi_select_end;
}
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
|
| ︙ | ︙ | |||
135964 135965 135966 135967 135968 135969 135970 135971 135972 135973 135974 135975 135976 135977 |
** the ORDER BY clause covers every term of the result set. Add
** terms to the ORDER BY clause as necessary.
*/
if( op!=TK_ALL ){
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
struct ExprList_item *pItem;
for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
assert( pItem->u.x.iOrderByCol>0 );
if( pItem->u.x.iOrderByCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
pNew->flags |= EP_IntValue;
| > | 136753 136754 136755 136756 136757 136758 136759 136760 136761 136762 136763 136764 136765 136766 136767 |
** the ORDER BY clause covers every term of the result set. Add
** terms to the ORDER BY clause as necessary.
*/
if( op!=TK_ALL ){
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
struct ExprList_item *pItem;
for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
assert( pItem!=0 );
assert( pItem->u.x.iOrderByCol>0 );
if( pItem->u.x.iOrderByCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
pNew->flags |= EP_IntValue;
|
| ︙ | ︙ | |||
135990 135991 135992 135993 135994 135995 135996 135997 135998 135999 136000 136001 136002 136003 |
** collation.
*/
aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
aPermute[0] = nOrderBy;
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
assert( pItem->u.x.iOrderByCol>0 );
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
}else{
pKeyMerge = 0;
| > | 136780 136781 136782 136783 136784 136785 136786 136787 136788 136789 136790 136791 136792 136793 136794 |
** collation.
*/
aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
aPermute[0] = nOrderBy;
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
assert( pItem!=0 );
assert( pItem->u.x.iOrderByCol>0 );
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
}else{
pKeyMerge = 0;
|
| ︙ | ︙ | |||
136302 136303 136304 136305 136306 136307 136308 |
}
}else{
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
pExpr->iTable = pSubst->iNewTable;
}
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
| | | 137093 137094 137095 137096 137097 137098 137099 137100 137101 137102 137103 137104 137105 137106 137107 |
}
}else{
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
pExpr->iTable = pSubst->iNewTable;
}
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
if( ExprUseXSelect(pExpr) ){
substSelect(pSubst, pExpr->x.pSelect, 1);
}else{
substExprList(pSubst, pExpr->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
Window *pWin = pExpr->y.pWin;
|
| ︙ | ︙ | |||
136789 136790 136791 136792 136793 136794 136795 |
}
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
if( pSrc->nSrc>1 ){
if( pParse->nSelect>500 ) return 0;
| | | 137580 137581 137582 137583 137584 137585 137586 137587 137588 137589 137590 137591 137592 137593 137594 |
}
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
if( pSrc->nSrc>1 ){
if( pParse->nSelect>500 ) return 0;
aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int));
if( aCsrMap ) aCsrMap[0] = pParse->nTab;
}
}
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
pSub->selId, pSub, iFrom));
|
| ︙ | ︙ | |||
137513 137514 137515 137516 137517 137518 137519 |
**
** This routine must be called after aggregate functions have been
** located but before their arguments have been subjected to aggregate
** analysis.
*/
static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
| | > > > | 138304 138305 138306 138307 138308 138309 138310 138311 138312 138313 138314 138315 138316 138317 138318 138319 138320 138321 138322 138323 138324 138325 138326 138327 138328 138329 138330 138331 138332 138333 138334 138335 |
**
** This routine must be called after aggregate functions have been
** located but before their arguments have been subjected to aggregate
** analysis.
*/
static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
ExprList *pEList; /* Arguments to agg function */
const char *zFunc; /* Name of aggregate function pFunc */
ExprList *pOrderBy;
u8 sortFlags = 0;
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
assert( !IsWindowFunc(pFunc) );
assert( ExprUseXList(pFunc) );
pEList = pFunc->x.pList;
if( pEList==0
|| pEList->nExpr!=1
|| ExprHasProperty(pFunc, EP_WinFunc)
|| OptimizationDisabled(db, SQLITE_MinMaxOpt)
){
return eRet;
}
assert( !ExprHasProperty(pFunc, EP_IntValue) );
zFunc = pFunc->u.zToken;
if( sqlite3StrICmp(zFunc, "min")==0 ){
eRet = WHERE_ORDERBY_MIN;
if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){
sortFlags = KEYINFO_ORDER_BIGNULL;
}
}else if( sqlite3StrICmp(zFunc, "max")==0 ){
|
| ︙ | ︙ | |||
137555 137556 137557 137558 137559 137560 137561 | ** The second argument is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** ** SELECT count(*) FROM <tbl> ** ** where table is a database table, not a sub-select or view. If the query ** does match this pattern, then a pointer to the Table object representing | | > > > > > > | > | > > < | | | > > | > > > | 138349 138350 138351 138352 138353 138354 138355 138356 138357 138358 138359 138360 138361 138362 138363 138364 138365 138366 138367 138368 138369 138370 138371 138372 138373 138374 138375 138376 138377 138378 138379 138380 138381 138382 138383 138384 138385 138386 138387 138388 138389 138390 138391 138392 138393 138394 138395 138396 |
** The second argument is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
**
** SELECT count(*) FROM <tbl>
**
** where table is a database table, not a sub-select or view. If the query
** does match this pattern, then a pointer to the Table object representing
** <tbl> is returned. Otherwise, NULL is returned.
**
** This routine checks to see if it is safe to use the count optimization.
** A correct answer is still obtained (though perhaps more slowly) if
** this routine returns NULL when it could have returned a table pointer.
** But returning the pointer when NULL should have been returned can
** result in incorrect answers and/or crashes. So, when in doubt, return NULL.
*/
static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
Table *pTab;
Expr *pExpr;
assert( !p->pGroupBy );
if( p->pWhere
|| p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1
|| p->pSrc->a[0].pSelect
|| pAggInfo->nFunc!=1
){
return 0;
}
pTab = p->pSrc->a[0].pTab;
assert( pTab!=0 );
assert( !IsView(pTab) );
if( !IsOrdinaryTable(pTab) ) return 0;
pExpr = p->pEList->a[0].pExpr;
assert( pExpr!=0 );
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( pExpr->pAggInfo!=pAggInfo ) return 0;
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
assert( pAggInfo->aFunc[0].pFExpr==pExpr );
testcase( ExprHasProperty(pExpr, EP_Distinct) );
testcase( ExprHasProperty(pExpr, EP_WinFunc) );
if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;
return pTab;
}
/*
** If the source-list item passed as an argument was augmented with an
|
| ︙ | ︙ | |||
137604 137605 137606 137607 137608 137609 137610 137611 137612 137613 137614 137615 137616 137617 |
pIdx=pIdx->pNext
);
if( !pIdx ){
sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
pParse->checkSchema = 1;
return SQLITE_ERROR;
}
pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
/*
** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
| > | 138411 138412 138413 138414 138415 138416 138417 138418 138419 138420 138421 138422 138423 138424 138425 |
pIdx=pIdx->pNext
);
if( !pIdx ){
sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
pParse->checkSchema = 1;
return SQLITE_ERROR;
}
assert( pFrom->fg.isCte==0 );
pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
/*
** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
|
| ︙ | ︙ | |||
137861 137862 137863 137864 137865 137866 137867 137868 137869 137870 137871 137872 137873 137874 |
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if( db->mallocFailed ) return 2;
pFrom->pSelect->selFlags |= SF_CopyCte;
assert( pFrom->pSelect );
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
pCteUse->eM10d = M10d_Yes;
}
| > > > > | 138669 138670 138671 138672 138673 138674 138675 138676 138677 138678 138679 138680 138681 138682 138683 138684 138685 138686 |
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if( db->mallocFailed ) return 2;
pFrom->pSelect->selFlags |= SF_CopyCte;
assert( pFrom->pSelect );
if( pFrom->fg.isIndexedBy ){
sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
return 2;
}
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
pCteUse->eM10d = M10d_Yes;
}
|
| ︙ | ︙ | |||
138496 138497 138498 138499 138500 138501 138502 |
&& pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg );
}
#endif
sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pFExpr;
| | | 139308 139309 139310 139311 139312 139313 139314 139315 139316 139317 139318 139319 139320 139321 139322 |
&& pAggInfo->aFunc[i].iMem<=pAggInfo->mxReg );
}
#endif
sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pFExpr;
assert( ExprUseXList(pE) );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
"argument");
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
|
| ︙ | ︙ | |||
138521 138522 138523 138524 138525 138526 138527 |
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
| | > | | 139333 139334 139335 139336 139337 139338 139339 139340 139341 139342 139343 139344 139345 139346 139347 139348 139349 |
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
}
/*
|
| ︙ | ︙ | |||
138556 138557 138558 138559 138560 138561 138562 |
struct AggInfo_col *pC;
pAggInfo->directMode = 1;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
int nArg;
int addrNext = 0;
int regAgg;
| | | > | 139369 139370 139371 139372 139373 139374 139375 139376 139377 139378 139379 139380 139381 139382 139383 139384 139385 139386 |
struct AggInfo_col *pC;
pAggInfo->directMode = 1;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
int nArg;
int addrNext = 0;
int regAgg;
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
&& regAcc
){
/* If regAcc==0, there there exists some min() or max() function
|
| ︙ | ︙ | |||
138804 138805 138806 138807 138808 138809 138810 138811 138812 138813 138814 138815 138816 138817 138818 |
sqlite3 *db;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
if( p->pWhere ) return 0;
if( p->pGroupBy ) return 0;
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
pSub = p->pSrc->a[0].pSelect;
if( pSub==0 ) return 0; /* The FROM is a subquery */
if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
| > > | 139618 139619 139620 139621 139622 139623 139624 139625 139626 139627 139628 139629 139630 139631 139632 139633 139634 |
sqlite3 *db;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
if( p->pWhere ) return 0;
if( p->pGroupBy ) return 0;
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
assert( ExprUseUToken(pExpr) );
if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
assert( ExprUseXList(pExpr) );
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
pSub = p->pSrc->a[0].pSelect;
if( pSub==0 ) return 0; /* The FROM is a subquery */
if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
|
| ︙ | ︙ | |||
139619 139620 139621 139622 139623 139624 139625 |
if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy);
}else{
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
| | | 140435 140436 140437 140438 140439 140440 140441 140442 140443 140444 140445 140446 140447 140448 140449 |
if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy);
}else{
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
assert( ExprUseXList(pExpr) );
sNC.ncFlags |= NC_InAggFunc;
sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
assert( !IsWindowFunc(pExpr) );
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
}
|
| ︙ | ︙ | |||
139674 139675 139676 139677 139678 139679 139680 |
int regReset; /* Return address register for reset subroutine */
ExprList *pDistinct = 0;
u16 distFlag = 0;
int eDist = WHERE_DISTINCT_NOOP;
if( pAggInfo->nFunc==1
&& pAggInfo->aFunc[0].iDistinct>=0
| > > | | 140490 140491 140492 140493 140494 140495 140496 140497 140498 140499 140500 140501 140502 140503 140504 140505 140506 |
int regReset; /* Return address register for reset subroutine */
ExprList *pDistinct = 0;
u16 distFlag = 0;
int eDist = WHERE_DISTINCT_NOOP;
if( pAggInfo->nFunc==1
&& pAggInfo->aFunc[0].iDistinct>=0
&& ALWAYS(pAggInfo->aFunc[0].pFExpr!=0)
&& ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr))
&& pAggInfo->aFunc[0].pFExpr->x.pList!=0
){
Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
pExpr = sqlite3ExprDup(db, pExpr, 0);
pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
|
| ︙ | ︙ | |||
139995 139996 139997 139998 139999 140000 140001 140002 140003 140004 140005 140006 140007 140008 |
}
}
if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
}else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
| > | 140813 140814 140815 140816 140817 140818 140819 140820 140821 140822 140823 140824 140825 140826 140827 |
}
}
if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
}else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) );
pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
|
| ︙ | ︙ | |||
140668 140669 140670 140671 140672 140673 140674 |
/* Make an entry in the sqlite_schema table */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
testcase( z==0 );
sqlite3NestedParse(pParse,
| | | 141487 141488 141489 141490 141491 141492 141493 141494 141495 141496 141497 141498 141499 141500 141501 |
/* Make an entry in the sqlite_schema table */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
testcase( z==0 );
sqlite3NestedParse(pParse,
"INSERT INTO %Q." LEGACY_SCHEMA_TABLE
" VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
db->aDb[iDb].zDbSName, zName,
pTrig->table, z);
sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddParseSchemaOp(v, iDb,
sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
|
| ︙ | ︙ | |||
140982 140983 140984 140985 140986 140987 140988 |
}
#endif
/* Generate code to destroy the database record of the trigger.
*/
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
| | | 141801 141802 141803 141804 141805 141806 141807 141808 141809 141810 141811 141812 141813 141814 141815 |
}
#endif
/* Generate code to destroy the database record of the trigger.
*/
if( (v = sqlite3GetVdbe(pParse))!=0 ){
sqlite3NestedParse(pParse,
"DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'",
db->aDb[iDb].zDbSName, pTrigger->zName
);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
}
}
|
| ︙ | ︙ | |||
142850 142851 142852 142853 142854 142855 142856 |
}
/*
** Return the number of rows that were changed, if we are tracking
** that information.
*/
if( regRowCount ){
| | < < | 143669 143670 143671 143672 143673 143674 143675 143676 143677 143678 143679 143680 143681 143682 143683 |
}
/*
** Return the number of rows that were changed, if we are tracking
** that information.
*/
if( regRowCount ){
sqlite3CodeChangeCount(v, regRowCount, "rows updated");
}
update_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprListDelete(db, pChanges);
|
| ︙ | ︙ | |||
143635 143636 143637 143638 143639 143640 143641 | rc = execSql(db, pzErrMsg, "BEGIN"); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Do not attempt to change the page size for a WAL database */ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) | | > > | 144452 144453 144454 144455 144456 144457 144458 144459 144460 144461 144462 144463 144464 144465 144466 144467 144468 |
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain))
==PAGER_JOURNALMODE_WAL
&& pOut==0
){
db->nextPagesize = 0;
}
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes, 0)
|| (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes, 0))
|| NEVER(db->mallocFailed)
){
|
| ︙ | ︙ | |||
144020 144021 144022 144023 144024 144025 144026 |
** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->u.vtab.p list.
*/
static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
VTable *pRet = 0;
| | > > > | 144839 144840 144841 144842 144843 144844 144845 144846 144847 144848 144849 144850 144851 144852 144853 144854 144855 144856 |
** p->u.vtab.p list to the sqlite3.pDisconnect lists of their associated
** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->u.vtab.p list.
*/
static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){
VTable *pRet = 0;
VTable *pVTable;
assert( IsVirtual(p) );
pVTable = p->u.vtab.p;
p->u.vtab.p = 0;
/* Assert that the mutex (if any) associated with the BtShared database
** that contains table p is held by the caller. See header comments
** above function sqlite3VtabUnlockList() for an explanation of why
** this makes it safe to access the sqlite3.pDisconnect list of any
** database connection that may have an entry in the p->u.vtab.p list.
|
| ︙ | ︙ | |||
144128 144129 144130 144131 144132 144133 144134 144135 144136 144137 144138 144139 144140 144141 144142 144143 144144 144145 144146 144147 144148 144149 144150 144151 |
** The reference count of the VTable structure associated with database
** connection db is decremented immediately (which may lead to the
** structure being xDisconnected and free). Any other VTable structures
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->u.vtab.azArg ){
int i;
for(i=0; i<p->u.vtab.nArg; i++){
if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
}
sqlite3DbFree(db, p->u.vtab.azArg);
}
}
/*
** Add a new module argument to pTable->u.vtab.azArg[].
** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
| > | > > > | 144950 144951 144952 144953 144954 144955 144956 144957 144958 144959 144960 144961 144962 144963 144964 144965 144966 144967 144968 144969 144970 144971 144972 144973 144974 144975 144976 144977 144978 144979 144980 144981 144982 144983 144984 144985 144986 144987 |
** The reference count of the VTable structure associated with database
** connection db is decremented immediately (which may lead to the
** structure being xDisconnected and free). Any other VTable structures
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
assert( IsVirtual(p) );
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->u.vtab.azArg ){
int i;
for(i=0; i<p->u.vtab.nArg; i++){
if( i!=1 ) sqlite3DbFree(db, p->u.vtab.azArg[i]);
}
sqlite3DbFree(db, p->u.vtab.azArg);
}
}
/*
** Add a new module argument to pTable->u.vtab.azArg[].
** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
sqlite3_int64 nBytes;
char **azModuleArg;
sqlite3 *db = pParse->db;
assert( IsVirtual(pTable) );
nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
}
azModuleArg = sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
if( azModuleArg==0 ){
sqlite3DbFree(db, zArg);
}else{
|
| ︙ | ︙ | |||
144234 144235 144236 144237 144238 144239 144240 144241 144242 144243 144244 144245 144246 144247 |
** has been completely parsed.
*/
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
Table *pTab = pParse->pNewTable; /* The table being constructed */
sqlite3 *db = pParse->db; /* The database connection */
if( pTab==0 ) return;
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
if( pTab->u.vtab.nArg<1 ) return;
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
** created now instead of just being read out of sqlite_schema) then
| > | 145060 145061 145062 145063 145064 145065 145066 145067 145068 145069 145070 145071 145072 145073 145074 |
** has been completely parsed.
*/
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
Table *pTab = pParse->pNewTable; /* The table being constructed */
sqlite3 *db = pParse->db; /* The database connection */
if( pTab==0 ) return;
assert( IsVirtual(pTab) );
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
if( pTab->u.vtab.nArg<1 ) return;
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
** created now instead of just being read out of sqlite_schema) then
|
| ︙ | ︙ | |||
144269 144270 144271 144272 144273 144274 144275 |
**
** The VM register number pParse->regRowid holds the rowid of an
** entry in the sqlite_schema table tht was created for this vtab
** by sqlite3StartTable().
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse,
| | | < | | < < < < | > | 145096 145097 145098 145099 145100 145101 145102 145103 145104 145105 145106 145107 145108 145109 145110 145111 145112 145113 145114 145115 145116 145117 145118 145119 145120 145121 145122 145123 145124 145125 145126 145127 145128 145129 145130 145131 145132 145133 145134 145135 145136 145137 |
**
** The VM register number pParse->regRowid holds the rowid of an
** entry in the sqlite_schema table tht was created for this vtab
** by sqlite3StartTable().
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE " "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#%d",
db->aDb[iDb].zDbSName,
pTab->zName,
pTab->zName,
zStmt,
pParse->regRowid
);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp0(v, OP_Expire);
zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
sqlite3VdbeLoadString(v, iReg, pTab->zName);
sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
}else{
/* If we are rereading the sqlite_schema table create the in-memory
** record of the table. */
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
assert( zName!=0 );
sqlite3MarkAllShadowTablesOf(db, pTab);
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab);
if( pOld ){
sqlite3OomFault(db);
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
pParse->pNewTable = 0;
|
| ︙ | ︙ | |||
144351 144352 144353 144354 144355 144356 144357 |
Module *pMod,
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
char **pzErr
){
VtabCtx sCtx;
VTable *pVTable;
int rc;
| | > > > | 145174 145175 145176 145177 145178 145179 145180 145181 145182 145183 145184 145185 145186 145187 145188 145189 145190 145191 145192 145193 145194 145195 145196 145197 |
Module *pMod,
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
char **pzErr
){
VtabCtx sCtx;
VTable *pVTable;
int rc;
const char *const*azArg;
int nArg = pTab->u.vtab.nArg;
char *zErr = 0;
char *zModuleName;
int iDb;
VtabCtx *pCtx;
assert( IsVirtual(pTab) );
azArg = (const char *const*)pTab->u.vtab.azArg;
/* Check that the virtual-table is not already being initialized */
for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
if( pCtx->pTab==pTab ){
*pzErr = sqlite3MPrintf(db,
"vtable constructor called recursively: %s", pTab->zName
);
return SQLITE_LOCKED;
|
| ︙ | ︙ | |||
144481 144482 144483 144484 144485 144486 144487 |
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
sqlite3 *db = pParse->db;
const char *zMod;
Module *pMod;
int rc;
assert( pTab );
| > | | 145307 145308 145309 145310 145311 145312 145313 145314 145315 145316 145317 145318 145319 145320 145321 145322 |
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
sqlite3 *db = pParse->db;
const char *zMod;
Module *pMod;
int rc;
assert( pTab );
assert( IsVirtual(pTab) );
if( sqlite3GetVTable(db, pTab) ){
return SQLITE_OK;
}
/* Locate the required virtual table module */
zMod = pTab->u.vtab.azArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod);
|
| ︙ | ︙ | |||
144685 144686 144687 144688 144689 144690 144691 |
** This call is a no-op if zTab is not a virtual table.
*/
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
int rc = SQLITE_OK;
Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
| > > | > | 145512 145513 145514 145515 145516 145517 145518 145519 145520 145521 145522 145523 145524 145525 145526 145527 145528 145529 |
** This call is a no-op if zTab is not a virtual table.
*/
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){
int rc = SQLITE_OK;
Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
if( ALWAYS(pTab!=0)
&& ALWAYS(IsVirtual(pTab))
&& ALWAYS(pTab->u.vtab.p!=0)
){
VTable *p;
int (*xDestroy)(sqlite3_vtab *);
for(p=pTab->u.vtab.p; p; p=p->pNext){
assert( p->pVtab );
if( p->pVtab->nRef>0 ){
return SQLITE_LOCKED;
}
|
| ︙ | ︙ | |||
144918 144919 144920 144921 144922 144923 144924 144925 144926 144927 144928 144929 144930 144931 | void *pArg = 0; FuncDef *pNew; int rc = 0; /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; | > | 145748 145749 145750 145751 145752 145753 145754 145755 145756 145757 145758 145759 145760 145761 145762 | void *pArg = 0; FuncDef *pNew; int rc = 0; /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; assert( ExprUseYTab(pExpr) ); pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; |
| ︙ | ︙ | |||
145212 145213 145214 145215 145216 145217 145218 145219 145220 145221 145222 145223 145224 145225 145226 145227 145228 145229 145230 145231 145232 |
int addrBody; /* Beginning of the body of this loop */
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
int iBase; /* Base register of multi-key index record */
int nPrefix; /* Number of prior entires in the key */
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
| > | | 146043 146044 146045 146046 146047 146048 146049 146050 146051 146052 146053 146054 146055 146056 146057 146058 146059 146060 146061 146062 146063 146064 146065 146066 146067 146068 146069 146070 146071 146072 |
int addrBody; /* Beginning of the body of this loop */
int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
int addrBignull; /* Jump here for next part of big-null scan */
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
int regFilter; /* Bloom filter */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to end the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
int nIn; /* Number of entries in aInLoop[] */
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
int iBase; /* Base register of multi-key index record */
int nPrefix; /* Number of prior entires in the key */
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
Index *pCoveringIdx; /* Possible covering index for WHERE_MULTI_OR */
} u;
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
Bitmask notReady; /* FROM entries not usable at this level */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrVisit; /* Address at which row is visited */
#endif
};
|
| ︙ | ︙ | |||
145440 145441 145442 145443 145444 145445 145446 145447 145448 |
** terms in the WHERE clause that are useful to the query planner.
*/
struct WhereScan {
WhereClause *pOrigWC; /* Original, innermost WhereClause */
WhereClause *pWC; /* WhereClause currently being scanned */
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
| > > > < < < | 146272 146273 146274 146275 146276 146277 146278 146279 146280 146281 146282 146283 146284 146285 146286 146287 146288 146289 146290 |
** terms in the WHERE clause that are useful to the query planner.
*/
struct WhereScan {
WhereClause *pOrigWC; /* Original, innermost WhereClause */
WhereClause *pWC; /* WhereClause currently being scanned */
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
int k; /* Resume scanning at this->pWC->a[this->k] */
u32 opMask; /* Acceptable operators */
char idxaff; /* Must match this affinity, if zCollName!=NULL */
unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */
unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
};
/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
|
| ︙ | ︙ | |||
145468 145469 145470 145471 145472 145473 145474 145475 145476 145477 145478 145479 145480 145481 |
struct WhereClause {
WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
u8 hasOr; /* True if any a[].eOperator is WO_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)
WhereTerm aStatic[1]; /* Initial static space for a[] */
#else
WhereTerm aStatic[8]; /* Initial static space for a[] */
#endif
};
| > | 146300 146301 146302 146303 146304 146305 146306 146307 146308 146309 146310 146311 146312 146313 146314 |
struct WhereClause {
WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
u8 hasOr; /* True if any a[].eOperator is WO_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
int nBase; /* Number of terms through the last non-Virtual */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)
WhereTerm aStatic[1]; /* Initial static space for a[] */
#else
WhereTerm aStatic[8]; /* Initial static space for a[] */
#endif
};
|
| ︙ | ︙ | |||
145525 145526 145527 145528 145529 145530 145531 |
*/
struct WhereMaskSet {
int bVarSelect; /* Used by sqlite3WhereExprUsage() */
int n; /* Number of assigned cursor values */
int ix[BMS]; /* Cursor assigned to each bit */
};
| < < < < < | 146358 146359 146360 146361 146362 146363 146364 146365 146366 146367 146368 146369 146370 146371 |
*/
struct WhereMaskSet {
int bVarSelect; /* Used by sqlite3WhereExprUsage() */
int n; /* Number of assigned cursor values */
int ix[BMS]; /* Cursor assigned to each bit */
};
/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
WhereInfo *pWInfo; /* Information about this WHERE */
WhereClause *pWC; /* WHERE clause terms */
|
| ︙ | ︙ | |||
145658 145659 145660 145661 145662 145663 145664 145665 145666 145667 145668 145669 145670 145671 145672 145673 | #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); #else # define sqlite3WhereExplainOneScan(u,v,w,x) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ | > > > > > > | 146486 146487 146488 146489 146490 146491 146492 146493 146494 146495 146496 146497 146498 146499 146500 146501 146502 146503 146504 146505 146506 146507 | #ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( const Parse *pParse, /* Parse context */ const WhereInfo *pWInfo, /* WHERE clause */ const WhereLevel *pLevel /* Bloom filter on this level */ ); #else # define sqlite3WhereExplainOneScan(u,v,w,x) 0 # define sqlite3WhereExplainBloomFilter(u,v,w) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ |
| ︙ | ︙ | |||
145752 145753 145754 145755 145756 145757 145758 145759 145760 145761 145762 145763 145764 145765 | #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN | > > | 146586 146587 146588 146589 146590 146591 146592 146593 146594 146595 146596 146597 146598 146599 146600 146601 | #define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */ #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ #define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ #define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ #endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN |
| ︙ | ︙ | |||
145914 145915 145916 145917 145918 145919 145920 |
}
if( zFmt ){
sqlite3_str_append(&str, " USING ", 7);
sqlite3_str_appendf(&str, zFmt, pIdx->zName);
explainIndexRange(&str, pLoop);
}
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
| > > > > > > | > > | > | | | | < | 146750 146751 146752 146753 146754 146755 146756 146757 146758 146759 146760 146761 146762 146763 146764 146765 146766 146767 146768 146769 146770 146771 146772 146773 146774 146775 146776 146777 146778 146779 146780 146781 146782 146783 146784 |
}
if( zFmt ){
sqlite3_str_append(&str, " USING ", 7);
sqlite3_str_appendf(&str, zFmt, pIdx->zName);
explainIndexRange(&str, pLoop);
}
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
char cRangeOp;
#if 0 /* Better output, but breaks many tests */
const Table *pTab = pItem->pTab;
const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName:
"rowid";
#else
const char *zRowid = "rowid";
#endif
sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid);
if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
cRangeOp = '=';
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
sqlite3_str_appendf(&str, ">? AND %s", zRowid);
cRangeOp = '<';
}else if( flags&WHERE_BTM_LIMIT ){
cRangeOp = '>';
}else{
assert( flags&WHERE_TOP_LIMIT);
cRangeOp = '<';
}
sqlite3_str_appendf(&str, "%c?)", cRangeOp);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
|
| ︙ | ︙ | |||
145949 145950 145951 145952 145953 145954 145955 145956 145957 145958 145959 145960 145961 145962 |
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
}
return ret;
}
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Configure the VM passed as the first argument with an
** sqlite3_stmt_scanstatus() entry corresponding to the scan used to
** implement level pLvl. Argument pSrclist is a pointer to the FROM
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 146793 146794 146795 146796 146797 146798 146799 146800 146801 146802 146803 146804 146805 146806 146807 146808 146809 146810 146811 146812 146813 146814 146815 146816 146817 146818 146819 146820 146821 146822 146823 146824 146825 146826 146827 146828 146829 146830 146831 146832 146833 146834 146835 146836 146837 146838 146839 146840 146841 146842 146843 146844 146845 146846 146847 146848 146849 146850 146851 146852 146853 146854 146855 146856 |
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
}
return ret;
}
/*
** Add a single OP_Explain opcode that describes a Bloom filter.
**
** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or
** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not
** required and this routine is a no-op.
**
** If an OP_Explain opcode is added to the VM, its address is returned.
** Otherwise, if no OP_Explain is coded, zero is returned.
*/
SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
const Parse *pParse, /* Parse context */
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
){
int ret = 0;
SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
int i; /* Loop counter */
WhereLoop *pLoop; /* The where loop */
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.printfFlags = SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
pLoop = pLevel->pWLoop;
if( pLoop->wsFlags & WHERE_IPK ){
const Table *pTab = pItem->pTab;
if( pTab->iPKey>=0 ){
sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
}else{
sqlite3_str_appendf(&str, "rowid=?");
}
}else{
for(i=pLoop->nSkip; i<pLoop->u.btree.nEq; i++){
const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i);
if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5);
sqlite3_str_appendf(&str, "%s=?", z);
}
}
sqlite3_str_append(&str, ")", 1);
zMsg = sqlite3StrAccumFinish(&str);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
return ret;
}
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
/*
** Configure the VM passed as the first argument with an
** sqlite3_stmt_scanstatus() entry corresponding to the scan used to
** implement level pLvl. Argument pSrclist is a pointer to the FROM
|
| ︙ | ︙ | |||
146154 146155 146156 146157 146158 146159 146160 |
WhereLoop *pLoop, /* The current loop */
Expr *pX /* The IN expression to be reduced */
){
sqlite3 *db = pParse->db;
Expr *pNew;
pNew = sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed==0 ){
| | | > > > > > > > | | 147048 147049 147050 147051 147052 147053 147054 147055 147056 147057 147058 147059 147060 147061 147062 147063 147064 147065 147066 147067 147068 147069 147070 147071 147072 147073 147074 147075 147076 147077 147078 |
WhereLoop *pLoop, /* The current loop */
Expr *pX /* The IN expression to be reduced */
){
sqlite3 *db = pParse->db;
Expr *pNew;
pNew = sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed==0 ){
ExprList *pOrigRhs; /* Original unmodified RHS */
ExprList *pOrigLhs; /* Original unmodified LHS */
ExprList *pRhs = 0; /* New RHS after modifications */
ExprList *pLhs = 0; /* New LHS after mods */
int i; /* Loop counter */
Select *pSelect; /* Pointer to the SELECT on the RHS */
assert( ExprUseXSelect(pNew) );
pOrigRhs = pNew->x.pSelect->pEList;
assert( pNew->pLeft!=0 );
assert( ExprUseXList(pNew->pLeft) );
pOrigLhs = pNew->pLeft->x.pList;
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
int iField;
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
assert( pOrigLhs->a[iField].pExpr!=0 );
pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr);
pOrigLhs->a[iField].pExpr = 0;
}
|
| ︙ | ︙ | |||
146278 146279 146280 146281 146282 146283 146284 |
}
for(i=iEq;i<pLoop->nLTerm; i++){
assert( pLoop->aLTerm[i]!=0 );
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
iTab = 0;
| | | 147179 147180 147181 147182 147183 147184 147185 147186 147187 147188 147189 147190 147191 147192 147193 |
}
for(i=iEq;i<pLoop->nLTerm; i++){
assert( pLoop->aLTerm[i]!=0 );
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
iTab = 0;
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
sqlite3 *db = pParse->db;
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
if( !db->mallocFailed ){
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
|
| ︙ | ︙ | |||
146300 146301 146302 146303 146304 146305 146306 |
if( eType==IN_INDEX_INDEX_DESC ){
testcase( bRev );
bRev = !bRev;
}
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
| < > | 147201 147202 147203 147204 147205 147206 147207 147208 147209 147210 147211 147212 147213 147214 147215 147216 |
if( eType==IN_INDEX_INDEX_DESC ){
testcase( bRev );
bRev = !bRev;
}
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}
|
| ︙ | ︙ | |||
146701 146702 146703 146704 146705 146706 146707 | sHint.iTabCur = iCur; sHint.iIdxCur = pLevel->iIdxCur; sHint.pIdx = pLoop->u.btree.pIndex; memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.u.pCCurHint = &sHint; pWC = &pWInfo->sWC; | | | 147602 147603 147604 147605 147606 147607 147608 147609 147610 147611 147612 147613 147614 147615 147616 |
sHint.iTabCur = iCur;
sHint.iIdxCur = pLevel->iIdxCur;
sHint.pIdx = pLoop->u.btree.pIndex;
memset(&sWalker, 0, sizeof(sWalker));
sWalker.pParse = pParse;
sWalker.u.pCCurHint = &sHint;
pWC = &pWInfo->sWC;
for(i=0; i<pWC->nBase; i++){
pTerm = &pWC->a[i];
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->prereqAll & pLevel->notReady ) continue;
/* Any terms specified as part of the ON(...) clause for any LEFT
** JOIN for which the current table is not the rhs are omitted
** from the cursor-hint.
|
| ︙ | ︙ | |||
146843 146844 146845 146846 146847 146848 146849 |
** this case, generate code to evaluate the expression and leave the
** result in register iReg.
*/
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
assert( nReg>0 );
if( p && sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
| | > > | | 147744 147745 147746 147747 147748 147749 147750 147751 147752 147753 147754 147755 147756 147757 147758 147759 147760 147761 147762 147763 147764 147765 147766 147767 147768 147769 147770 |
** this case, generate code to evaluate the expression and leave the
** result in register iReg.
*/
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
assert( nReg>0 );
if( p && sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
if( ExprUseXSelect(p) ){
Vdbe *v = pParse->pVdbe;
int iSelect;
assert( p->op==TK_SELECT );
iSelect = sqlite3CodeSubselect(pParse, p);
sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
}else
#endif
{
int i;
const ExprList *pList;
assert( ExprUseXList(p) );
pList = p->x.pList;
assert( nReg<=pList->nExpr );
for(i=0; i<nReg; i++){
sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
}
}
}else{
assert( nReg==1 || pParse->nErr );
|
| ︙ | ︙ | |||
146906 146907 146908 146909 146910 146911 146912 |
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
| < | > | | 147809 147810 147811 147812 147813 147814 147815 147816 147817 147818 147819 147820 147821 147822 147823 147824 147825 147826 147827 147828 147829 147830 147831 147832 147833 147834 147835 147836 147837 147838 147839 147840 147841 |
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
testcase( ExprHasProperty(pExpr, EP_Skip) );
testcase( ExprHasProperty(pExpr, EP_Unlikely) );
ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn);
pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
}
}
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
/* A walker node callback that translates a column reference to a table
** into a corresponding column reference of an index.
*/
static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
if( pExpr->op==TK_COLUMN ){
IdxExprTrans *pX = p->u.pIdxTrans;
if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
assert( ExprUseYTab(pExpr) && pExpr->y.pTab!=0 );
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->y.pTab = 0;
}
}
|
| ︙ | ︙ | |||
146972 146973 146974 146975 146976 146977 146978 |
x.iTabCur = iTabCur;
x.iIdxCur = iIdxCur;
x.pWInfo = pWInfo;
x.db = pWInfo->pParse->db;
for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
i16 iRef = pIdx->aiColumn[iIdxCol];
if( iRef==XN_EXPR ){
| | | 147875 147876 147877 147878 147879 147880 147881 147882 147883 147884 147885 147886 147887 147888 147889 |
x.iTabCur = iTabCur;
x.iIdxCur = iIdxCur;
x.pWInfo = pWInfo;
x.db = pWInfo->pParse->db;
for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
i16 iRef = pIdx->aiColumn[iIdxCol];
if( iRef==XN_EXPR ){
assert( aColExpr!=0 && aColExpr->a[iIdxCol].pExpr!=0 );
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
w.xExprCallback = whereIndexExprTransNode;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( iRef>=0
&& (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
&& ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
|
| ︙ | ︙ | |||
147029 147030 147031 147032 147033 147034 147035 147036 147037 147038 147039 147040 147041 147042 |
if( pTerm->wtFlags & TERM_CODED ) continue;
pExpr = pTerm->pExpr;
if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){
pTerm->wtFlags |= TERM_CODED;
}
}
}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Parse *pParse, /* Parsing context */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 147932 147933 147934 147935 147936 147937 147938 147939 147940 147941 147942 147943 147944 147945 147946 147947 147948 147949 147950 147951 147952 147953 147954 147955 147956 147957 147958 147959 147960 147961 147962 147963 147964 147965 147966 147967 147968 147969 147970 147971 147972 147973 147974 147975 147976 147977 147978 147979 147980 147981 147982 147983 147984 147985 147986 147987 147988 147989 147990 147991 147992 147993 147994 147995 147996 147997 147998 147999 148000 148001 148002 |
if( pTerm->wtFlags & TERM_CODED ) continue;
pExpr = pTerm->pExpr;
if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){
pTerm->wtFlags |= TERM_CODED;
}
}
}
/*
** This routine is called right after An OP_Filter has been generated and
** before the corresponding index search has been performed. This routine
** checks to see if there are additional Bloom filters in inner loops that
** can be checked prior to doing the index lookup. If there are available
** inner-loop Bloom filters, then evaluate those filters now, before the
** index lookup. The idea is that a Bloom filter check is way faster than
** an index lookup, and the Bloom filter might return false, meaning that
** the index lookup can be skipped.
**
** We know that an inner loop uses a Bloom filter because it has the
** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked,
** then clear the WhereLevel.regFilter value to prevent the Bloom filter
** from being checked a second time when the inner loop is evaluated.
*/
static SQLITE_NOINLINE void filterPullDown(
Parse *pParse, /* Parsing context */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
int addrNxt, /* Jump here to bypass inner loops */
Bitmask notReady /* Loops that are not ready */
){
while( ++iLevel < pWInfo->nLevel ){
WhereLevel *pLevel = &pWInfo->a[iLevel];
WhereLoop *pLoop = pLevel->pWLoop;
if( pLevel->regFilter==0 ) continue;
/* ,--- Because constructBloomFilter() has will not have set
** vvvvv--' pLevel->regFilter if this were true. */
if( NEVER(pLoop->prereq & notReady) ) continue;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
int regRowid;
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
regRowid = sqlite3GetTempReg(pParse);
regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, regRowid, 1);
VdbeCoverage(pParse->pVdbe);
}else{
u16 nEq = pLoop->u.btree.nEq;
int r1;
char *zStartAff;
assert( pLoop->wsFlags & WHERE_INDEXED );
r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
}
}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Parse *pParse, /* Parsing context */
|
| ︙ | ︙ | |||
147161 147162 147163 147164 147165 147166 147167 |
pLoop->u.vtab.needFree = 0;
/* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
** the u.vtab.idxStr. NULL it out to prevent a use-after-free */
if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
| > > | > > > | 148121 148122 148123 148124 148125 148126 148127 148128 148129 148130 148131 148132 148133 148134 148135 148136 148137 148138 148139 148140 |
pLoop->u.vtab.needFree = 0;
/* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
** the u.vtab.idxStr. NULL it out to prevent a use-after-free */
if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
if( pLoop->wsFlags & WHERE_IN_ABLE ){
iIn = pLevel->u.in.nIn;
}else{
iIn = 0;
}
for(j=nConstraint-1; j>=0; j--){
pTerm = pLoop->aLTerm[j];
if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
disableTerm(pLevel, pTerm);
}else if( (pTerm->eOperator & WO_IN)!=0
&& sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
|
| ︙ | ︙ | |||
147235 147236 147237 147238 147239 147240 147241 147242 147243 147244 147245 147246 147247 147248 |
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iReleaseReg = ++pParse->nMem;
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
pLevel->op = OP_Noop;
}else if( (pLoop->wsFlags & WHERE_IPK)!=0
&& (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
){
/* Case 3: We have an inequality comparison against the ROWID field.
| > > > > > > | 148200 148201 148202 148203 148204 148205 148206 148207 148208 148209 148210 148211 148212 148213 148214 148215 148216 148217 148218 148219 |
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iReleaseReg = ++pParse->nMem;
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
addrNxt = pLevel->addrNxt;
if( pLevel->regFilter ){
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
iRowidReg, 1);
VdbeCoverage(v);
filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
}
sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
pLevel->op = OP_Noop;
}else if( (pLoop->wsFlags & WHERE_IPK)!=0
&& (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
){
/* Case 3: We have an inequality comparison against the ROWID field.
|
| ︙ | ︙ | |||
147560 147561 147562 147563 147564 147565 147566 147567 147568 147569 147570 147571 147572 147573 |
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
}
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
assert( regBignull==0 );
/* TUNING: The OP_SeekScan opcode seeks to reduce the number
** of expensive seek operations by replacing a single seek with
| > > > > > > | 148531 148532 148533 148534 148535 148536 148537 148538 148539 148540 148541 148542 148543 148544 148545 148546 148547 148548 148549 148550 |
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
}
if( pLevel->regFilter ){
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
regBase, nEq);
VdbeCoverage(v);
filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
}
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
assert( regBignull==0 );
/* TUNING: The OP_SeekScan opcode seeks to reduce the number
** of expensive seek operations by replacing a single seek with
|
| ︙ | ︙ | |||
147608 147609 147610 147611 147612 147613 147614 147615 147616 147617 147618 147619 147620 147621 147622 147623 |
}
}
/* Load the value for the inequality constraint at the end of the
** range (if any).
*/
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
VdbeCoverage(v);
| > > > > > > > > > > > | 148585 148586 148587 148588 148589 148590 148591 148592 148593 148594 148595 148596 148597 148598 148599 148600 148601 148602 148603 148604 148605 148606 148607 148608 148609 148610 148611 |
}
}
/* Load the value for the inequality constraint at the end of the
** range (if any).
*/
nConstraint = nEq;
assert( pLevel->p2==0 );
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
if( addrSeekScan ){
/* For a seek-scan that has a range on the lowest term of the index,
** we have to make the top of the loop be code that sets the end
** condition of the range. Otherwise, the OP_SeekScan might jump
** over that initialization, leaving the range-end value set to the
** range-start value, resulting in a wrong answer.
** See ticket 5981a8c041a3c2f3 (2021-11-02).
*/
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
}
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
VdbeCoverage(v);
|
| ︙ | ︙ | |||
147643 147644 147645 147646 147647 147648 147649 |
}
nConstraint++;
}
sqlite3DbFree(db, zStartAff);
sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
| | | 148631 148632 148633 148634 148635 148636 148637 148638 148639 148640 148641 148642 148643 148644 148645 |
}
nConstraint++;
}
sqlite3DbFree(db, zStartAff);
sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
if( pLevel->p2==0 ) pLevel->p2 = sqlite3VdbeCurrentAddr(v);
/* Check if the index cursor is past the end of the range. */
if( nConstraint ){
if( regBignull ){
/* Except, skip the end-of-range check while doing the NULL-scan */
sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
VdbeComment((v, "If NULL-scan 2nd pass"));
|
| ︙ | ︙ | |||
148050 148051 148052 148053 148054 148055 148056 |
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
| > > > | | 149038 149039 149040 149041 149042 149043 149044 149045 149046 149047 149048 149049 149050 149051 149052 149053 149054 149055 |
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
assert( pLevel->pWLoop==pLoop );
assert( (pLoop->wsFlags & WHERE_MULTI_OR)!=0 );
assert( (pLoop->wsFlags & WHERE_IN_ABLE)==0 );
pLevel->u.pCoveringIdx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeGoto(v, pLevel->addrBrk);
|
| ︙ | ︙ | |||
148177 148178 148179 148180 148181 148182 148183 | ** of the "==" operator. ** ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" ** and we are coding the t1 loop and the t2 loop has not yet coded, ** then we cannot use the "t1.a=t2.b" constraint, but we can code ** the implied "t1.a=123" constraint. */ | | > | | 149168 149169 149170 149171 149172 149173 149174 149175 149176 149177 149178 149179 149180 149181 149182 149183 149184 149185 149186 149187 149188 149189 149190 149191 149192 149193 149194 149195 149196 149197 149198 149199 149200 149201 149202 149203 149204 149205 |
** of the "==" operator.
**
** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
** and we are coding the t1 loop and the t2 loop has not yet coded,
** then we cannot use the "t1.a=t2.b" constraint, but we can code
** the implied "t1.a=123" constraint.
*/
for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
Expr *pE, sEAlt;
WhereTerm *pAlt;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
if( pTabItem->fg.jointype & JT_LEFT ) continue;
pE = pTerm->pExpr;
#ifdef WHERETRACE_ENABLED /* 0x800 */
if( sqlite3WhereTrace & 0x800 ){
sqlite3DebugPrintf("Coding transitive constraint:\n");
sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
}
#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
if( (pAlt->eOperator & WO_IN)
&& ExprUseXSelect(pAlt->pExpr)
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
){
continue;
}
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IS );
testcase( pAlt->eOperator & WO_IN );
|
| ︙ | ︙ | |||
148221 148222 148223 148224 148225 148226 148227 |
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
| | | 149213 149214 149215 149216 149217 149218 149219 149220 149221 149222 149223 149224 149225 149226 149227 |
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
|
| ︙ | ︙ | |||
148332 148333 148334 148335 148336 148337 148338 148339 148340 148341 148342 148343 148344 148345 |
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqlite3DbFree(db, pOld);
}
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
}
pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p);
pTerm->wtFlags = wtFlags;
| > | 149324 149325 149326 149327 149328 149329 149330 149331 149332 149333 149334 149335 149336 149337 149338 |
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqlite3DbFree(db, pOld);
}
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm;
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlite3LogEst(p->iTable) - 270;
}else{
pTerm->truthProb = 1;
}
pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p);
pTerm->wtFlags = wtFlags;
|
| ︙ | ︙ | |||
148448 148449 148450 148451 148452 148453 148454 148455 148456 148457 148458 148459 148460 148461 148462 148463 148464 148465 148466 148467 148468 148469 |
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){
return 0;
}
#ifdef SQLITE_EBCDIC
if( *pnoCase ) return 0;
#endif
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
op = pRight->op;
if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = sqlite3_value_text(pVal);
}
sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
| > > | | 149441 149442 149443 149444 149445 149446 149447 149448 149449 149450 149451 149452 149453 149454 149455 149456 149457 149458 149459 149460 149461 149462 149463 149464 149465 149466 149467 149468 149469 149470 149471 149472 |
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){
return 0;
}
#ifdef SQLITE_EBCDIC
if( *pnoCase ) return 0;
#endif
assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
op = pRight->op;
if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = sqlite3_value_text(pVal);
}
sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
assert( !ExprHasProperty(pRight, EP_IntValue) );
z = (u8*)pRight->u.zToken;
}
if( z ){
/* Count the number of prefix characters prior to the first wildcard */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
|
| ︙ | ︙ | |||
148492 148493 148494 148495 148496 148497 148498 |
/* A "complete" match if the pattern ends with "*" or "%" */
*pisComplete = c==wc[0] && z[cnt+1]==0;
/* Get the pattern prefix. Remove all escapes from the prefix. */
pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
if( pPrefix ){
int iFrom, iTo;
| > > | | 149487 149488 149489 149490 149491 149492 149493 149494 149495 149496 149497 149498 149499 149500 149501 149502 149503 |
/* A "complete" match if the pattern ends with "*" or "%" */
*pisComplete = c==wc[0] && z[cnt+1]==0;
/* Get the pattern prefix. Remove all escapes from the prefix. */
pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
if( pPrefix ){
int iFrom, iTo;
char *zNew;
assert( !ExprHasProperty(pPrefix, EP_IntValue) );
zNew = pPrefix->u.zToken;
zNew[cnt] = 0;
for(iFrom=iTo=0; iFrom<cnt; iFrom++){
if( zNew[iFrom]==wc[3] ) iFrom++;
zNew[iTo++] = zNew[iFrom];
}
zNew[iTo] = 0;
assert( iTo>0 );
|
| ︙ | ︙ | |||
148516 148517 148518 148519 148520 148521 148522 |
** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
*/
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
| > > | | 149513 149514 149515 149516 149517 149518 149519 149520 149521 149522 149523 149524 149525 149526 149527 149528 149529 |
** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
*/
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| (ALWAYS( ExprUseYTab(pLeft) )
&& pLeft->y.pTab
&& IsVirtual(pLeft->y.pTab)) /* Might be numeric */
){
int isNum;
double rDummy;
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
if( isNum<=0 ){
if( iTo==1 && zNew[0]=='-' ){
isNum = +1;
|
| ︙ | ︙ | |||
148544 148545 148546 148547 148548 148549 148550 148551 148552 148553 148554 148555 148556 148557 |
*ppPrefix = pPrefix;
/* If the RHS pattern is a bound parameter, make arrangements to
** reprepare the statement when that parameter is rebound */
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeSetVarmask(v, pRight->iColumn);
if( *pisComplete && pRight->u.zToken[1] ){
/* If the rhs of the LIKE expression is a variable, and the current
** value of the variable means there is no need to invoke the LIKE
** function, then no OP_Variable will be added to the program.
** This causes problems for the sqlite3_bind_parameter_name()
** API. To work around them, add a dummy OP_Variable here.
*/
| > | 149543 149544 149545 149546 149547 149548 149549 149550 149551 149552 149553 149554 149555 149556 149557 |
*ppPrefix = pPrefix;
/* If the RHS pattern is a bound parameter, make arrangements to
** reprepare the statement when that parameter is rebound */
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeSetVarmask(v, pRight->iColumn);
assert( !ExprHasProperty(pRight, EP_IntValue) );
if( *pisComplete && pRight->u.zToken[1] ){
/* If the rhs of the LIKE expression is a variable, and the current
** value of the variable means there is no need to invoke the LIKE
** function, then no OP_Variable will be added to the program.
** This causes problems for the sqlite3_bind_parameter_name()
** API. To work around them, add a dummy OP_Variable here.
*/
|
| ︙ | ︙ | |||
148617 148618 148619 148620 148621 148622 148623 148624 148625 148626 148627 148628 148629 148630 148631 148632 148633 148634 148635 148636 148637 148638 148639 148640 148641 148642 148643 148644 148645 148646 148647 148648 148649 148650 148651 148652 148653 148654 148655 148656 148657 148658 148659 148660 148661 148662 148663 148664 148665 148666 148667 148668 |
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
{ "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
};
ExprList *pList;
Expr *pCol; /* Column reference */
int i;
pList = pExpr->x.pList;
if( pList==0 || pList->nExpr!=2 ){
return 0;
}
/* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a
** virtual table on their second argument, which is the same as
** the left-hand side operand in their in-fix form.
**
** vtab_column MATCH expression
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
for(i=0; i<ArraySize(aOp); i++){
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
*ppRight = pList->a[0].pExpr;
*ppLeft = pCol;
return 1;
}
}
}
/* We can also match against the first column of overloaded
** functions where xFindFunction returns a value of at least
** SQLITE_INDEX_CONSTRAINT_FUNCTION.
**
** OVERLOADED(vtab_column,expression)
**
** Historically, xFindFunction expected to see lower-case function
** names. But for this use case, xFindFunction is expected to deal
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
| > > > > > | > > | 149617 149618 149619 149620 149621 149622 149623 149624 149625 149626 149627 149628 149629 149630 149631 149632 149633 149634 149635 149636 149637 149638 149639 149640 149641 149642 149643 149644 149645 149646 149647 149648 149649 149650 149651 149652 149653 149654 149655 149656 149657 149658 149659 149660 149661 149662 149663 149664 149665 149666 149667 149668 149669 149670 149671 149672 149673 149674 149675 149676 149677 149678 149679 149680 149681 149682 149683 149684 149685 149686 149687 149688 149689 149690 149691 149692 149693 149694 149695 149696 149697 149698 149699 149700 149701 |
{ "like", SQLITE_INDEX_CONSTRAINT_LIKE },
{ "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
};
ExprList *pList;
Expr *pCol; /* Column reference */
int i;
assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
if( pList==0 || pList->nExpr!=2 ){
return 0;
}
/* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a
** virtual table on their second argument, which is the same as
** the left-hand side operand in their in-fix form.
**
** vtab_column MATCH expression
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
for(i=0; i<ArraySize(aOp); i++){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
*ppRight = pList->a[0].pExpr;
*ppLeft = pCol;
return 1;
}
}
}
/* We can also match against the first column of overloaded
** functions where xFindFunction returns a value of at least
** SQLITE_INDEX_CONSTRAINT_FUNCTION.
**
** OVERLOADED(vtab_column,expression)
**
** Historically, xFindFunction expected to see lower-case function
** names. But for this use case, xFindFunction is expected to deal
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pMod = (sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction!=0 ){
i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed);
if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
*peOp2 = i;
*ppRight = pList->a[1].pExpr;
*ppLeft = pCol;
return 1;
}
}
}
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
if( ExprIsVtab(pLeft) ){
res++;
}
assert( pRight==0 || pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
if( pRight && ExprIsVtab(pRight) ){
res++;
SWAP(Expr*, pLeft, pRight);
}
*ppLeft = pLeft;
*ppRight = pRight;
|
| ︙ | ︙ | |||
148933 148934 148935 148936 148937 148938 148939 148940 148941 148942 148943 148944 148945 148946 |
WhereClause *pAndWC;
WhereTerm *pAndTerm;
int j;
Bitmask b = 0;
pOrTerm->u.pAndInfo = pAndInfo;
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pAndWC = &pAndInfo->wc;
memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic));
sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
sqlite3WhereExprAnalyze(pSrc, pAndWC);
pAndWC->pOuter = pWC;
if( !db->mallocFailed ){
| > | 149940 149941 149942 149943 149944 149945 149946 149947 149948 149949 149950 149951 149952 149953 149954 |
WhereClause *pAndWC;
WhereTerm *pAndTerm;
int j;
Bitmask b = 0;
pOrTerm->u.pAndInfo = pAndInfo;
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pOrTerm->leftCursor = -1;
pAndWC = &pAndInfo->wc;
memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic));
sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
sqlite3WhereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
sqlite3WhereExprAnalyze(pSrc, pAndWC);
pAndWC->pOuter = pWC;
if( !db->mallocFailed ){
|
| ︙ | ︙ | |||
148975 148976 148977 148978 148979 148980 148981 | } /* ** Record the set of tables that satisfy case 3. The set might be ** empty. */ pOrInfo->indexable = indexable; | < | > > < < | 149983 149984 149985 149986 149987 149988 149989 149990 149991 149992 149993 149994 149995 149996 149997 149998 149999 150000 |
}
/*
** Record the set of tables that satisfy case 3. The set might be
** empty.
*/
pOrInfo->indexable = indexable;
pTerm->eOperator = WO_OR;
pTerm->leftCursor = -1;
if( indexable ){
pWC->hasOr = 1;
}
/* For a two-way OR, attempt to implementation case 2.
*/
if( indexable && pOrWc->nTerm==2 ){
int iOne = 0;
WhereTerm *pOne;
|
| ︙ | ︙ | |||
149052 149053 149054 149055 149056 149057 149058 149059 149060 149061 149062 149063 149064 149065 149066 149067 149068 149069 149070 149071 149072 149073 149074 149075 149076 149077 149078 149079 149080 149081 149082 149083 149084 149085 |
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
}
if( i<0 ){
/* No candidate table+column was found. This can only occur
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
/* We have found a candidate table and column. Check to see if that
** table and column is common to every term in the OR clause */
okToChngToIN = 1;
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
}else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
}else{
| > > | 150059 150060 150061 150062 150063 150064 150065 150066 150067 150068 150069 150070 150071 150072 150073 150074 150075 150076 150077 150078 150079 150080 150081 150082 150083 150084 150085 150086 150087 150088 150089 150090 150091 150092 150093 150094 |
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
}
if( i<0 ){
/* No candidate table+column was found. This can only occur
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
assert( chngToIN==sqlite3WhereGetMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
/* We have found a candidate table and column. Check to see if that
** table and column is common to every term in the OR clause */
okToChngToIN = 1;
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
}else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
}else{
|
| ︙ | ︙ | |||
149108 149109 149110 149111 149112 149113 149114 149115 149116 149117 149118 149119 149120 149121 149122 149123 149124 149125 149126 |
ExprList *pList = 0; /* The RHS of the IN operator */
Expr *pLeft = 0; /* The LHS of the IN operator */
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft, 0);
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
| > | | 150117 150118 150119 150120 150121 150122 150123 150124 150125 150126 150127 150128 150129 150130 150131 150132 150133 150134 150135 150136 150137 150138 150139 150140 150141 150142 150143 150144 |
ExprList *pList = 0; /* The RHS of the IN operator */
Expr *pLeft = 0; /* The LHS of the IN operator */
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft, 0);
pNew = sqlite3PExpr(pParse, TK_IN, pDup, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
assert( ExprUseXList(pNew) );
pNew->x.pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
/* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
|
| ︙ | ︙ | |||
149248 149249 149250 149251 149252 149253 149254 149255 149256 149257 149258 149259 149260 149261 |
/* If this expression is a vector to the left or right of a
** inequality constraint (>, <, >= or <=), perform the processing
** on the first element of the vector. */
assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
pExpr = pExpr->x.pList->a[0].pExpr;
}
if( pExpr->op==TK_COLUMN ){
aiCurCol[0] = pExpr->iTable;
aiCurCol[1] = pExpr->iColumn;
| > | 150258 150259 150260 150261 150262 150263 150264 150265 150266 150267 150268 150269 150270 150271 150272 |
/* If this expression is a vector to the left or right of a
** inequality constraint (>, <, >= or <=), perform the processing
** on the first element of the vector. */
assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
assert( ExprUseXList(pExpr) );
pExpr = pExpr->x.pList->a[0].pExpr;
}
if( pExpr->op==TK_COLUMN ){
aiCurCol[0] = pExpr->iTable;
aiCurCol[1] = pExpr->iColumn;
|
| ︙ | ︙ | |||
149305 149306 149307 149308 149309 149310 149311 149312 149313 149314 149315 149316 149317 149318 149319 149320 |
sqlite3 *db = pParse->db; /* Database connection */
unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */
int nLeft; /* Number of elements on left side vector */
if( db->mallocFailed ){
return;
}
pTerm = &pWC->a[idxTerm];
pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
| > > > | < | > > > > > > > | > | > > | > > > > > | | 150316 150317 150318 150319 150320 150321 150322 150323 150324 150325 150326 150327 150328 150329 150330 150331 150332 150333 150334 150335 150336 150337 150338 150339 150340 150341 150342 150343 150344 150345 150346 150347 150348 150349 150350 150351 150352 150353 150354 150355 150356 150357 150358 150359 150360 150361 150362 150363 150364 150365 150366 150367 150368 |
sqlite3 *db = pParse->db; /* Database connection */
unsigned char eOp2 = 0; /* op2 value for LIKE/REGEXP/GLOB */
int nLeft; /* Number of elements on left side vector */
if( db->mallocFailed ){
return;
}
assert( pWC->nTerm > idxTerm );
pTerm = &pWC->a[idxTerm];
pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr!=0 ); /* Because malloc() has not failed */
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
pMaskSet->bVarSelect = 0;
prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
if( ExprUseXSelect(pExpr) ){
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
}else{
pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
}
prereqAll = prereqLeft | pTerm->prereqRight;
}else{
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
if( pExpr->pLeft==0
|| ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow)
|| pExpr->x.pList!=0
){
prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
}else{
prereqAll = prereqLeft | pTerm->prereqRight;
}
}
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
#ifdef SQLITE_DEBUG
if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
printf("\n*** Incorrect prereqAll computed for:\n");
sqlite3TreeViewExpr(0,pExpr,0);
abort();
}
#endif
if( ExprHasProperty(pExpr, EP_FromJoin) ){
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
prereqAll |= x;
extraRight = x-1; /* ON clause terms may not be used with an index
** on left table of a LEFT JOIN. Ticket #3015 */
if( (prereqAll>>1)>=x ){
sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
|
| ︙ | ︙ | |||
149350 149351 149352 149353 149354 149355 149356 149357 149358 149359 149360 149361 149362 149363 149364 149365 149366 149367 149368 |
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
&& !ExprHasProperty(pRight, EP_FixedCol)
| > > | 150378 150379 150380 150381 150382 150383 150384 150385 150386 150387 150388 150389 150390 150391 150392 150393 150394 150395 150396 150397 150398 |
Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
assert( ExprUseXList(pLeft) );
pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
&& !ExprHasProperty(pRight, EP_FixedCol)
|
| ︙ | ︙ | |||
149392 149393 149394 149395 149396 149397 149398 149399 149400 149401 149402 149403 149404 149405 149406 149407 149408 149409 149410 149411 149412 149413 149414 149415 |
}
}else{
pDup = pExpr;
pNew = pTerm;
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}else
if( op==TK_ISNULL
&& !ExprHasProperty(pExpr,EP_FromJoin)
&& 0==sqlite3ExprCanBeNull(pLeft)
){
pExpr->op = TK_TRUEFALSE;
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
pTerm->prereqAll = 0;
pTerm->eOperator = 0;
}
}
| > > | 150422 150423 150424 150425 150426 150427 150428 150429 150430 150431 150432 150433 150434 150435 150436 150437 150438 150439 150440 150441 150442 150443 150444 150445 150446 150447 |
}
}else{
pDup = pExpr;
pNew = pTerm;
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}else
if( op==TK_ISNULL
&& !ExprHasProperty(pExpr,EP_FromJoin)
&& 0==sqlite3ExprCanBeNull(pLeft)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pExpr->op = TK_TRUEFALSE;
pExpr->u.zToken = "false";
ExprSetProperty(pExpr, EP_IsFalse);
pTerm->prereqAll = 0;
pTerm->eOperator = 0;
}
}
|
| ︙ | ︙ | |||
149427 149428 149429 149430 149431 149432 149433 |
** The two new terms are added onto the end of the WhereClause object.
** The new terms are "dynamic" and are children of the original BETWEEN
** term. That means that if the BETWEEN term is coded, the children are
** skipped. Or, if the children are satisfied by an index, the original
** BETWEEN term is skipped.
*/
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
| | > > | 150459 150460 150461 150462 150463 150464 150465 150466 150467 150468 150469 150470 150471 150472 150473 150474 150475 150476 150477 |
** The two new terms are added onto the end of the WhereClause object.
** The new terms are "dynamic" and are children of the original BETWEEN
** term. That means that if the BETWEEN term is coded, the children are
** skipped. Or, if the children are satisfied by an index, the original
** BETWEEN term is skipped.
*/
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
ExprList *pList;
int i;
static const u8 ops[] = {TK_GE, TK_LE};
assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
|
| ︙ | ︙ | |||
149522 149523 149524 149525 149526 149527 149528 149529 149530 149531 149532 149533 149534 149535 149536 149537 |
Expr *pNewExpr1;
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
const char *zCollSeqName; /* Name of collating sequence */
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
/* Convert the lower bound to upper-case and the upper bound to
** lower-case (upper-case is less than lower-case in ASCII) so that
** the range constraints also work for BLOBs
*/
if( noCase && !pParse->db->mallocFailed ){
int i;
| > > > > | 150556 150557 150558 150559 150560 150561 150562 150563 150564 150565 150566 150567 150568 150569 150570 150571 150572 150573 150574 150575 |
Expr *pNewExpr1;
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
const char *zCollSeqName; /* Name of collating sequence */
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
assert( ExprUseXList(pExpr) );
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) );
assert( pStr2==0 || !ExprHasProperty(pStr2, EP_IntValue) );
/* Convert the lower bound to upper-case and the upper bound to
** lower-case (upper-case is less than lower-case in ASCII) so that
** the range constraints also work for BLOBs
*/
if( noCase && !pParse->db->mallocFailed ){
int i;
|
| ︙ | ︙ | |||
149623 149624 149625 149626 149627 149628 149629 149630 149631 149632 149633 149634 149635 149636 |
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
else if( pExpr->op==TK_IN
&& pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
&& pWC->op==TK_AND
){
int i;
| > | 150661 150662 150663 150664 150665 150666 150667 150668 150669 150670 150671 150672 150673 150674 150675 |
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
else if( pExpr->op==TK_IN
&& pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& ALWAYS( ExprUseXSelect(pExpr) )
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
&& pWC->op==TK_AND
){
int i;
|
| ︙ | ︙ | |||
149739 149740 149741 149742 149743 149744 149745 149746 149747 149748 149749 149750 149751 149752 149753 149754 149755 |
WhereClause *pWC, /* The WhereClause to be initialized */
WhereInfo *pWInfo /* The WHERE processing context */
){
pWC->pWInfo = pWInfo;
pWC->hasOr = 0;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
}
/*
** Deallocate a WhereClause structure. The WhereClause structure
** itself is not freed. This routine is the inverse of
** sqlite3WhereClauseInit().
*/
SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){
| > < < > | > > > > > > > > > > | | | > | > | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > < < < < < < | | > > > > > > > > > > | 150778 150779 150780 150781 150782 150783 150784 150785 150786 150787 150788 150789 150790 150791 150792 150793 150794 150795 150796 150797 150798 150799 150800 150801 150802 150803 150804 150805 150806 150807 150808 150809 150810 150811 150812 150813 150814 150815 150816 150817 150818 150819 150820 150821 150822 150823 150824 150825 150826 150827 150828 150829 150830 150831 150832 150833 150834 150835 150836 150837 150838 150839 150840 150841 150842 150843 150844 150845 150846 150847 150848 150849 150850 150851 150852 150853 150854 150855 150856 150857 150858 150859 150860 150861 150862 150863 150864 150865 150866 150867 150868 150869 150870 150871 150872 150873 150874 150875 150876 150877 150878 150879 150880 150881 150882 150883 150884 150885 150886 150887 150888 150889 150890 150891 150892 150893 150894 150895 150896 150897 150898 150899 150900 150901 150902 |
WhereClause *pWC, /* The WhereClause to be initialized */
WhereInfo *pWInfo /* The WHERE processing context */
){
pWC->pWInfo = pWInfo;
pWC->hasOr = 0;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nBase = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
}
/*
** Deallocate a WhereClause structure. The WhereClause structure
** itself is not freed. This routine is the inverse of
** sqlite3WhereClauseInit().
*/
SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){
sqlite3 *db = pWC->pWInfo->pParse->db;
assert( pWC->nTerm>=pWC->nBase );
if( pWC->nTerm>0 ){
WhereTerm *a = pWC->a;
WhereTerm *aLast = &pWC->a[pWC->nTerm-1];
#ifdef SQLITE_DEBUG
int i;
/* Verify that every term past pWC->nBase is virtual */
for(i=pWC->nBase; i<pWC->nTerm; i++){
assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 );
}
#endif
while(1){
if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
}
if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){
if( a->wtFlags & TERM_ORINFO ){
assert( (a->wtFlags & TERM_ANDINFO)==0 );
whereOrInfoDelete(db, a->u.pOrInfo);
}else{
assert( (a->wtFlags & TERM_ANDINFO)!=0 );
whereAndInfoDelete(db, a->u.pAndInfo);
}
}
if( a==aLast ) break;
a++;
}
}
if( pWC->a!=pWC->aStatic ){
sqlite3DbFree(db, pWC->a);
}
}
/*
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
**
** sqlite3WhereExprUsage(MaskSet, Expr) ->
**
** Return a Bitmask of all tables referenced by Expr. Expr can be
** be NULL, in which case 0 is returned.
**
** sqlite3WhereExprUsageNN(MaskSet, Expr) ->
**
** Same as sqlite3WhereExprUsage() except that Expr must not be
** NULL. The "NN" suffix on the name stands for "Not Null".
**
** sqlite3WhereExprListUsage(MaskSet, ExprList) ->
**
** Return a Bitmask of all tables referenced by every expression
** in the expression list ExprList. ExprList can be NULL, in which
** case 0 is returned.
**
** sqlite3WhereExprUsageFull(MaskSet, ExprList) ->
**
** Internal use only. Called only by sqlite3WhereExprUsageNN() for
** complex expressions that require pushing register values onto
** the stack. Many calls to sqlite3WhereExprUsageNN() do not need
** the more complex analysis done by this routine. Hence, the
** computations done by this routine are broken out into a separate
** "no-inline" function to avoid the stack push overhead in the
** common case where it is not needed.
*/
static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull(
WhereMaskSet *pMaskSet,
Expr *p
){
Bitmask mask;
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
if( p->pRight ){
mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
assert( p->x.pList==0 );
}else if( ExprUseXSelect(p) ){
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
}else if( p->x.pList ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && ExprUseYWin(p) ){
assert( p->y.pWin!=0 );
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
}
#endif
return mask;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return sqlite3WhereGetMask(pMaskSet, p->iTable);
}else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
assert( p->op!=TK_IF_NULL_ROW );
return 0;
}
return sqlite3WhereExprUsageFull(pMaskSet, p);
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
int i;
Bitmask mask = 0;
|
| ︙ | ︙ | |||
149868 149869 149870 149871 149872 149873 149874 149875 149876 149877 149878 149879 149880 149881 |
pTab->zName, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
pColRef->y.pTab = pTab;
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
if( pItem->fg.jointype & JT_LEFT ){
sqlite3SetJoinExpr(pTerm, pItem->iCursor);
}
| > | 150957 150958 150959 150960 150961 150962 150963 150964 150965 150966 150967 150968 150969 150970 150971 |
pTab->zName, j);
return;
}
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
assert( ExprUseYTab(pColRef) );
pColRef->y.pTab = pTab;
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
if( pItem->fg.jointype & JT_LEFT ){
sqlite3SetJoinExpr(pTerm, pItem->iCursor);
}
|
| ︙ | ︙ | |||
150117 150118 150119 150120 150121 150122 150123 |
/*
** Return the bitmask for the given cursor number. Return 0 if
** iCursor is not in the set.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
int i;
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
| > > > > > | | 151207 151208 151209 151210 151211 151212 151213 151214 151215 151216 151217 151218 151219 151220 151221 151222 151223 151224 151225 151226 |
/*
** Return the bitmask for the given cursor number. Return 0 if
** iCursor is not in the set.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
int i;
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 );
assert( iCursor>=-1 );
if( pMaskSet->ix[0]==iCursor ){
return 1;
}
for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i);
}
}
return 0;
}
|
| ︙ | ︙ | |||
150169 150170 150171 150172 150173 150174 150175 150176 150177 150178 150179 150180 150181 150182 150183 150184 |
assert( pScan->iEquiv<=pScan->nEquiv );
pWC = pScan->pWC;
while(1){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pWC!=0 );
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
| > > | 151264 151265 151266 151267 151268 151269 151270 151271 151272 151273 151274 151275 151276 151277 151278 151279 151280 151281 |
assert( pScan->iEquiv<=pScan->nEquiv );
pWC = pScan->pWC;
while(1){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pWC!=0 );
assert( iCur>=0 );
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
|
| ︙ | ︙ | |||
150212 150213 150214 150215 150216 150217 150218 |
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
}
}
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
| | > | 151309 151310 151311 151312 151313 151314 151315 151316 151317 151318 151319 151320 151321 151322 151323 151324 |
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
}
}
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
&& (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
&& pX->op==TK_COLUMN
&& pX->iTable==pScan->aiCur[0]
&& pX->iColumn==pScan->aiColumn[0]
){
testcase( pTerm->eOperator & WO_IS );
continue;
}
pScan->pWC = pWC;
|
| ︙ | ︙ | |||
150299 150300 150301 150302 150303 150304 150305 |
pScan->k = 0;
pScan->aiCur[0] = iCur;
pScan->nEquiv = 1;
pScan->iEquiv = 1;
if( pIdx ){
int j = iColumn;
iColumn = pIdx->aiColumn[j];
| > > > > > | < < < < < | 151397 151398 151399 151400 151401 151402 151403 151404 151405 151406 151407 151408 151409 151410 151411 151412 151413 151414 151415 151416 151417 151418 151419 151420 |
pScan->k = 0;
pScan->aiCur[0] = iCur;
pScan->nEquiv = 1;
pScan->iEquiv = 1;
if( pIdx ){
int j = iColumn;
iColumn = pIdx->aiColumn[j];
if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
pScan->zCollName = pIdx->azColl[j];
}else if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
pScan->aiColumn[0] = XN_EXPR;
return whereScanInitIndexExpr(pScan);
}
}else if( iColumn==XN_EXPR ){
return 0;
}
pScan->aiColumn[0] = iColumn;
return whereScanNext(pScan);
}
|
| ︙ | ︙ | |||
150592 150593 150594 150595 150596 150597 150598 | #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* ** Return TRUE if the WHERE clause term pTerm is of a form where it ** could be used with an index to access pSrc, assuming an appropriate ** index existed. */ static int termCanDriveIndex( | | | | > | | | | | 151690 151691 151692 151693 151694 151695 151696 151697 151698 151699 151700 151701 151702 151703 151704 151705 151706 151707 151708 151709 151710 151711 151712 151713 151714 151715 151716 151717 151718 151719 151720 151721 151722 151723 151724 151725 151726 151727 151728 151729 151730 151731 151732 151733 151734 151735 151736 151737 151738 151739 151740 151741 |
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
** could be used with an index to access pSrc, assuming an appropriate
** index existed.
*/
static int termCanDriveIndex(
const WhereTerm *pTerm, /* WHERE clause term to check */
const SrcItem *pSrc, /* Table we are trying to access */
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
if( (pSrc->fg.jointype & JT_LEFT)
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
&& (pTerm->eOperator & WO_IS)
){
/* Cannot use an IS term from the WHERE clause as an index driver for
** the RHS of a LEFT JOIN. Such a term can only be used if it is from
** the ON clause. */
return 0;
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pTerm->u.x.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1;
}
#endif
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Generate code to construct the Index object for an automatic index
** and to set up the WhereLevel object pLevel so that the code generator
** makes use of the automatic index.
*/
static SQLITE_NOINLINE void constructAutomaticIndex(
Parse *pParse, /* The parsing context */
const WhereClause *pWC, /* The WHERE clause */
const SrcItem *pSrc, /* The FROM clause term to get the next index */
const Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
int nKeyCol; /* Number of columns in the constructed index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
WhereTerm *pWCEnd; /* End of pWC->a[] */
Index *pIdx; /* Object describing the transient index */
Vdbe *v; /* Prepared statement under construction */
|
| ︙ | ︙ | |||
150670 150671 150672 150673 150674 150675 150676 |
nKeyCol = 0;
pTable = pSrc->pTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
| | < | < > | | | > > > > | | | 151769 151770 151771 151772 151773 151774 151775 151776 151777 151778 151779 151780 151781 151782 151783 151784 151785 151786 151787 151788 151789 151790 151791 151792 151793 151794 151795 151796 151797 151798 |
nKeyCol = 0;
pTable = pSrc->pTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
/* Make the automatic index a partial index if there are terms in the
** WHERE clause (or the ON clause of a LEFT join) that constrain which
** rows of the target table (pSrc) that can be used. */
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& ((pSrc->fg.jointype&JT_LEFT)==0 || ExprHasProperty(pExpr,EP_FromJoin))
&& sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor)
){
pPartial = sqlite3ExprAnd(pParse, pPartial,
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol;
Bitmask cMask;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
iCol = pTerm->u.x.leftColumn;
cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
if( !sentWarning ){
sqlite3_log(SQLITE_WARNING_AUTOINDEX,
"automatic index on %s(%s)", pTable->zName,
pTable->aCol[iCol].zCnName);
sentWarning = 1;
|
| ︙ | ︙ | |||
150734 150735 150736 150737 150738 150739 150740 |
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
pIdx->pTable = pTable;
n = 0;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
| > > > | | | 151836 151837 151838 151839 151840 151841 151842 151843 151844 151845 151846 151847 151848 151849 151850 151851 151852 151853 151854 |
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
pIdx->pTable = pTable;
n = 0;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol;
Bitmask cMask;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
iCol = pTerm->u.x.leftColumn;
cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS-1 );
testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
| ︙ | ︙ | |||
150777 150778 150779 150780 150781 150782 150783 150784 150785 150786 150787 150788 150789 150790 |
/* Create the automatic index */
assert( pLevel->iIdxCur>=0 );
pLevel->iIdxCur = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
| > > > > | 151882 151883 151884 151885 151886 151887 151888 151889 151890 151891 151892 151893 151894 151895 151896 151897 151898 151899 |
/* Create the automatic index */
assert( pLevel->iIdxCur>=0 );
pLevel->iIdxCur = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "for %s", pTable->zName));
if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
pLevel->regFilter = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter);
}
/* Fill the automatic index with content */
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
|
| ︙ | ︙ | |||
150799 150800 150801 150802 150803 150804 150805 150806 150807 150808 150809 150810 150811 150812 |
sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
pLoop->wsFlags |= WHERE_PARTIALIDX;
}
regRecord = sqlite3GetTempReg(pParse);
regBase = sqlite3GenerateIndexKey(
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pTabItem->fg.viaCoroutine ){
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
testcase( pParse->db->mallocFailed );
assert( pLevel->iIdxCur>0 );
| > > > > | 151908 151909 151910 151911 151912 151913 151914 151915 151916 151917 151918 151919 151920 151921 151922 151923 151924 151925 |
sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
pLoop->wsFlags |= WHERE_PARTIALIDX;
}
regRecord = sqlite3GetTempReg(pParse);
regBase = sqlite3GenerateIndexKey(
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
if( pLevel->regFilter ){
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
regBase, pLoop->u.btree.nEq);
}
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pTabItem->fg.viaCoroutine ){
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
testcase( pParse->db->mallocFailed );
assert( pLevel->iIdxCur>0 );
|
| ︙ | ︙ | |||
150824 150825 150826 150827 150828 150829 150830 150831 150832 150833 150834 150835 150836 150837 | /* Jump here when skipping the initialization */ sqlite3VdbeJumpHere(v, addrInit); end_auto_index_create: sqlite3ExprDelete(pParse->db, pPartial); } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite3_free(). */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 151937 151938 151939 151940 151941 151942 151943 151944 151945 151946 151947 151948 151949 151950 151951 151952 151953 151954 151955 151956 151957 151958 151959 151960 151961 151962 151963 151964 151965 151966 151967 151968 151969 151970 151971 151972 151973 151974 151975 151976 151977 151978 151979 151980 151981 151982 151983 151984 151985 151986 151987 151988 151989 151990 151991 151992 151993 151994 151995 151996 151997 151998 151999 152000 152001 152002 152003 152004 152005 152006 152007 152008 152009 152010 152011 152012 152013 152014 152015 152016 152017 152018 152019 152020 152021 152022 152023 152024 152025 152026 152027 152028 152029 152030 152031 152032 152033 152034 152035 152036 152037 152038 152039 152040 152041 152042 152043 152044 152045 152046 152047 152048 152049 152050 152051 152052 152053 152054 152055 152056 152057 152058 152059 152060 152061 152062 152063 152064 152065 152066 152067 |
/* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit);
end_auto_index_create:
sqlite3ExprDelete(pParse->db, pPartial);
}
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
/*
** Generate bytecode that will initialize a Bloom filter that is appropriate
** for pLevel.
**
** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER
** flag set, initialize a Bloomfilter for them as well. Except don't do
** this recursive initialization if the SQLITE_BloomPulldown optimization has
** been turned off.
**
** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared
** from the loop, but the regFilter value is set to a register that implements
** the Bloom filter. When regFilter is positive, the
** sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter
** and skip the subsequence B-Tree seek if the Bloom filter indicates that
** no matching rows exist.
**
** This routine may only be called if it has previously been determined that
** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit
** is set.
*/
static SQLITE_NOINLINE void constructBloomFilter(
WhereInfo *pWInfo, /* The WHERE clause */
int iLevel, /* Index in pWInfo->a[] that is pLevel */
WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */
Bitmask notReady /* Loops that are not ready */
){
int addrOnce; /* Address of opening OP_Once */
int addrTop; /* Address of OP_Rewind */
int addrCont; /* Jump here to skip a row */
const WhereTerm *pTerm; /* For looping over WHERE clause terms */
const WhereTerm *pWCEnd; /* Last WHERE clause term */
Parse *pParse = pWInfo->pParse; /* Parsing context */
Vdbe *v = pParse->pVdbe; /* VDBE under construction */
WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */
int iCur; /* Cursor for table getting the filter */
assert( pLoop!=0 );
assert( v!=0 );
assert( pLoop->wsFlags & WHERE_BLOOMFILTER );
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
do{
const SrcItem *pItem;
const Table *pTab;
u64 sz;
sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel);
addrCont = sqlite3VdbeMakeLabel(pParse);
iCur = pLevel->iTabCur;
pLevel->regFilter = ++pParse->nMem;
/* The Bloom filter is a Blob held in a register. Initialize it
** to zero-filled blob of at least 80K bits, but maybe more if the
** estimated size of the table is larger. We could actually
** measure the size of the table at run-time using OP_Count with
** P3==1 and use that value to initialize the blob. But that makes
** testing complicated. By basing the blob size on the value in the
** sqlite_stat1 table, testing is much easier.
*/
pItem = &pWInfo->pTabList->a[pLevel->iFrom];
assert( pItem!=0 );
pTab = pItem->pTab;
assert( pTab!=0 );
sz = sqlite3LogEstToInt(pTab->nRowLogEst);
if( sz<10000 ){
sz = 10000;
}else if( sz>10000000 ){
sz = 10000000;
}
sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
if( (pTerm->wtFlags & TERM_VIRTUAL)==0
&& sqlite3ExprIsTableConstant(pExpr, iCur)
){
sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
}
}
if( pLoop->wsFlags & WHERE_IPK ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1);
sqlite3ReleaseTempReg(pParse, r1);
}else{
Index *pIdx = pLoop->u.btree.pIndex;
int n = pLoop->u.btree.nEq;
int r1 = sqlite3GetTempRange(pParse, n);
int jj;
for(jj=0; jj<n; jj++){
int iCol = pIdx->aiColumn[jj];
assert( pIdx->pTable==pItem->pTab );
sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj);
}
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
sqlite3ReleaseTempRange(pParse, r1, n);
}
sqlite3VdbeResolveLabel(v, addrCont);
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrTop);
pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
while( iLevel < pWInfo->nLevel ){
iLevel++;
pLevel = &pWInfo->a[iLevel];
pLoop = pLevel->pWLoop;
if( pLoop==0 ) continue;
if( pLoop->prereq & notReady ) continue;
if( pLoop->wsFlags & WHERE_BLOOMFILTER ) break;
}
}while( iLevel < pWInfo->nLevel );
sqlite3VdbeJumpHere(v, addrOnce);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Allocate and populate an sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite3_free().
*/
|
| ︙ | ︙ | |||
150862 150863 150864 150865 150866 150867 150868 150869 150870 150871 150872 150873 150874 150875 |
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
testcase( pTerm->eOperator & WO_IN );
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( pTerm->u.x.leftColumn>=(-1) );
nTerm++;
}
/* If the ORDER BY clause contains only columns in the current
** virtual table then allocate space for the aOrderBy part of
** the sqlite3_index_info structure.
| > | 152092 152093 152094 152095 152096 152097 152098 152099 152100 152101 152102 152103 152104 152105 152106 |
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
testcase( pTerm->eOperator & WO_IN );
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pTerm->u.x.leftColumn>=(-1) );
nTerm++;
}
/* If the ORDER BY clause contains only columns in the current
** virtual table then allocate space for the aOrderBy part of
** the sqlite3_index_info structure.
|
| ︙ | ︙ | |||
150922 150923 150924 150925 150926 150927 150928 150929 150930 150931 150932 150933 150934 150935 |
** right-hand table of a LEFT JOIN. See tag-20191211-001 for the
** equivalent restriction for ordinary tables. */
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
){
continue;
}
assert( pTerm->u.x.leftColumn>=(-1) );
pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
if( op==WO_AUX ){
pIdxCons[j].op = pTerm->eMatchOp;
| > | 152153 152154 152155 152156 152157 152158 152159 152160 152161 152162 152163 152164 152165 152166 152167 |
** right-hand table of a LEFT JOIN. See tag-20191211-001 for the
** equivalent restriction for ordinary tables. */
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
){
continue;
}
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pTerm->u.x.leftColumn>=(-1) );
pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
if( op==WO_AUX ){
pIdxCons[j].op = pTerm->eMatchOp;
|
| ︙ | ︙ | |||
151685 151686 151687 151688 151689 151690 151691 151692 151693 151694 151695 151696 151697 151698 151699 151700 151701 151702 151703 151704 151705 151706 151707 151708 |
char zLeft[50];
memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
pTerm->u.pOrInfo->indexable);
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
sqlite3DebugPrintf(
"TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
/* The 0x10000 .wheretrace flag causes extra information to be
** shown about each Term */
if( sqlite3WhereTrace & 0x10000 ){
sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
| > | | 152917 152918 152919 152920 152921 152922 152923 152924 152925 152926 152927 152928 152929 152930 152931 152932 152933 152934 152935 152936 152937 152938 152939 152940 152941 152942 152943 152944 152945 152946 152947 152948 152949 |
char zLeft[50];
memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
pTerm->u.pOrInfo->indexable);
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
sqlite3DebugPrintf(
"TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
/* The 0x10000 .wheretrace flag causes extra information to be
** shown about each Term */
if( sqlite3WhereTrace & 0x10000 ){
sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
if( (pTerm->eOperator & (WO_OR|WO_AND))==0 && pTerm->u.x.iField ){
sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
}
if( pTerm->iParent>=0 ){
sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
}
sqlite3DebugPrintf("\n");
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
|
| ︙ | ︙ | |||
151764 151765 151766 151767 151768 151769 151770 |
}else{
z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
}
sqlite3DebugPrintf(" %-19s", z);
sqlite3_free(z);
}
if( p->wsFlags & WHERE_SKIPSCAN ){
| | | | 152997 152998 152999 153000 153001 153002 153003 153004 153005 153006 153007 153008 153009 153010 153011 153012 153013 |
}else{
z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
}
sqlite3DebugPrintf(" %-19s", z);
sqlite3_free(z);
}
if( p->wsFlags & WHERE_SKIPSCAN ){
sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
}else{
sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm);
}
sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
int i;
for(i=0; i<p->nLTerm; i++){
sqlite3WhereTermPrint(p->aLTerm[i], i);
}
|
| ︙ | ︙ | |||
151866 151867 151868 151869 151870 151871 151872 |
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
int i;
assert( pWInfo!=0 );
for(i=0; i<pWInfo->nLevel; i++){
WhereLevel *pLevel = &pWInfo->a[i];
| | > | 153099 153100 153101 153102 153103 153104 153105 153106 153107 153108 153109 153110 153111 153112 153113 153114 |
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
int i;
assert( pWInfo!=0 );
for(i=0; i<pWInfo->nLevel; i++){
WhereLevel *pLevel = &pWInfo->a[i];
if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE)!=0 ){
assert( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0 );
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
}
sqlite3WhereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
pWInfo->pLoops = p->pNextLoop;
|
| ︙ | ︙ | |||
152225 152226 152227 152228 152229 152230 152231 |
){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j;
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
| | | | > > > > > > > | 153459 153460 153461 153462 153463 153464 153465 153466 153467 153468 153469 153470 153471 153472 153473 153474 153475 153476 153477 153478 153479 153480 153481 153482 153483 153484 153485 153486 153487 153488 153489 153490 153491 |
){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j;
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
assert( pTerm!=0 );
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue;
for(j=pLoop->nLTerm-1; j>=0; j--){
pX = pLoop->aLTerm[j];
if( pX==0 ) continue;
if( pX==pTerm ) break;
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ){
if( pLoop->maskSelf==pTerm->prereqAll ){
/* If there are extra terms in the WHERE clause not used by an index
** that depend only on the table being scanned, and that will tend to
** cause many rows to be omitted, then mark that table as
** "self-culling". */
pLoop->wsFlags |= WHERE_SELFCULL;
}
if( pTerm->truthProb<=0 ){
/* If a truth probability is specified using the likelihood() hints,
** then use the probability provided by the application. */
pLoop->nOut += pTerm->truthProb;
}else{
/* In the absence of explicit truth probabilities, use heuristics to
** guess a reasonable truth probability. */
|
| ︙ | ︙ | |||
152264 152265 152266 152267 152268 152269 152270 |
pTerm->wtFlags |= TERM_HEURTRUTH;
iReduce = k;
}
}
}
}
}
| | > > | 153505 153506 153507 153508 153509 153510 153511 153512 153513 153514 153515 153516 153517 153518 153519 153520 153521 |
pTerm->wtFlags |= TERM_HEURTRUTH;
iReduce = k;
}
}
}
}
}
if( pLoop->nOut > nRow-iReduce ){
pLoop->nOut = nRow - iReduce;
}
}
/*
** Term pTerm is a vector range comparison operation. The first comparison
** in the vector can be optimized using column nEq of the index. This
** function returns the total number of vector elements that can be used
** as part of the range comparison.
|
| ︙ | ︙ | |||
152301 152302 152303 152304 152305 152306 152307 |
nCmp = MIN(nCmp, (pIdx->nColumn - nEq));
for(i=1; i<nCmp; i++){
/* Test if comparison i of pTerm is compatible with column (i+nEq)
** of the index. If not, exit the loop. */
char aff; /* Comparison affinity */
char idxaff = 0; /* Indexed columns affinity */
CollSeq *pColl; /* Comparison collation sequence */
| > > > | | | | 153544 153545 153546 153547 153548 153549 153550 153551 153552 153553 153554 153555 153556 153557 153558 153559 153560 153561 153562 153563 |
nCmp = MIN(nCmp, (pIdx->nColumn - nEq));
for(i=1; i<nCmp; i++){
/* Test if comparison i of pTerm is compatible with column (i+nEq)
** of the index. If not, exit the loop. */
char aff; /* Comparison affinity */
char idxaff = 0; /* Indexed columns affinity */
CollSeq *pColl; /* Comparison collation sequence */
Expr *pLhs, *pRhs;
assert( ExprUseXList(pTerm->pExpr->pLeft) );
pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
pRhs = pTerm->pExpr->pRight;
if( ExprUseXSelect(pRhs) ){
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
}else{
pRhs = pRhs->x.pList->a[i].pExpr;
}
/* Check that the LHS of the comparison is a column reference to
** the right column of the right source table. And that the sort
|
| ︙ | ︙ | |||
152464 152465 152466 152467 152468 152469 152470 |
|| (pNew->wsFlags & WHERE_COLUMN_NULL)!=0
|| (pNew->wsFlags & WHERE_COLUMN_IN)!=0
|| (pNew->wsFlags & WHERE_SKIPSCAN)!=0
);
if( eOp & WO_IN ){
Expr *pExpr = pTerm->pExpr;
| | | 153710 153711 153712 153713 153714 153715 153716 153717 153718 153719 153720 153721 153722 153723 153724 |
|| (pNew->wsFlags & WHERE_COLUMN_NULL)!=0
|| (pNew->wsFlags & WHERE_COLUMN_IN)!=0
|| (pNew->wsFlags & WHERE_SKIPSCAN)!=0
);
if( eOp & WO_IN ){
Expr *pExpr = pTerm->pExpr;
if( ExprUseXSelect(pExpr) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
nIn = 46; assert( 46==sqlite3LogEst(25) );
/* The expression may actually be of the form (x, y) IN (SELECT...).
** In this case there is a separate term for each of (x) and (y).
** However, the nIn multiplier should only be applied once, not once
|
| ︙ | ︙ | |||
152605 152606 152607 152608 152609 152610 152611 |
pNew->nOut -= nIn;
}else{
#ifdef SQLITE_ENABLE_STAT4
tRowcnt nOut = 0;
if( nInMul==0
&& pProbe->nSample
&& ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
| | | 153851 153852 153853 153854 153855 153856 153857 153858 153859 153860 153861 153862 153863 153864 153865 |
pNew->nOut -= nIn;
}else{
#ifdef SQLITE_ENABLE_STAT4
tRowcnt nOut = 0;
if( nInMul==0
&& pProbe->nSample
&& ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
&& ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr))
&& OptimizationEnabled(db, SQLITE_Stat4)
){
Expr *pExpr = pTerm->pExpr;
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
testcase( eOp & WO_EQ );
testcase( eOp & WO_IS );
testcase( eOp & WO_ISNULL );
|
| ︙ | ︙ | |||
152881 152882 152883 152884 152885 152886 152887 152888 152889 152890 152891 152892 152893 152894 |
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
pTab = pSrc->pTab;
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
if( pSrc->fg.isIndexedBy ){
/* An INDEXED BY clause specifies a particular index to use */
pProbe = pSrc->u2.pIBIndex;
}else if( !HasRowid(pTab) ){
pProbe = pTab->pIndex;
}else{
/* There is no INDEXED BY clause. Create a fake Index object in local
** variable sPk to represent the rowid primary key index. Make this
| > | 154127 154128 154129 154130 154131 154132 154133 154134 154135 154136 154137 154138 154139 154140 154141 |
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
pTab = pSrc->pTab;
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
if( pSrc->fg.isIndexedBy ){
assert( pSrc->fg.isCte==0 );
/* An INDEXED BY clause specifies a particular index to use */
pProbe = pSrc->u2.pIBIndex;
}else if( !HasRowid(pTab) ){
pProbe = pTab->pIndex;
}else{
/* There is no INDEXED BY clause. Create a fake Index object in local
** variable sPk to represent the rowid primary key index. Make this
|
| ︙ | ︙ | |||
153496 153497 153498 153499 153500 153501 153502 153503 153504 153505 153506 153507 153508 153509 |
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifdef WHERETRACE_ENABLED
| > | 154743 154744 154745 154746 154747 154748 154749 154750 154751 154752 154753 154754 154755 154756 154757 |
if( (pOrTerm->eOperator & WO_AND)!=0 ){
sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
}else if( pOrTerm->leftCursor==iCur ){
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.nBase = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
continue;
}
sCur.n = 0;
#ifdef WHERETRACE_ENABLED
|
| ︙ | ︙ | |||
153967 153968 153969 153970 153971 153972 153973 |
}
}
}
} /* End the loop over all WhereLoops from outer-most down to inner-most */
if( obSat==obDone ) return (i8)nOrderBy;
if( !isOrderDistinct ){
for(i=nOrderBy-1; i>0; i--){
| | | 155215 155216 155217 155218 155219 155220 155221 155222 155223 155224 155225 155226 155227 155228 155229 |
}
}
}
} /* End the loop over all WhereLoops from outer-most down to inner-most */
if( obSat==obDone ) return (i8)nOrderBy;
if( !isOrderDistinct ){
for(i=nOrderBy-1; i>0; i--){
Bitmask m = ALWAYS(i<BMS) ? MASKBIT(i) - 1 : 0;
if( (obSat&m)==m ) return i;
}
return 0;
}
return -1;
}
|
| ︙ | ︙ | |||
154492 154493 154494 154495 154496 154497 154498 154499 154500 |
if( pItem->fg.isIndexedBy ) return 0;
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
pLoop->nSkip = 0;
pTerm = whereScanInit(&scan, pWC, iCur, -1, WO_EQ|WO_IS, 0);
if( pTerm ){
testcase( pTerm->eOperator & WO_IS );
| > < | 155740 155741 155742 155743 155744 155745 155746 155747 155748 155749 155750 155751 155752 155753 155754 155755 155756 |
if( pItem->fg.isIndexedBy ) return 0;
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
pLoop->nSkip = 0;
pTerm = whereScanInit(&scan, pWC, iCur, -1, WO_EQ|WO_IS, 0);
while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan);
if( pTerm ){
testcase( pTerm->eOperator & WO_IS );
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
pLoop->aLTerm[0] = pTerm;
pLoop->nLTerm = 1;
pLoop->u.btree.nEq = 1;
/* TUNING: Cost of a rowid lookup is 10 */
pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
}else{
|
| ︙ | ︙ | |||
154602 154603 154604 154605 154606 154607 154608 154609 154610 154611 154612 154613 154614 154615 |
}
}
}
# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C)
#else
# define WHERETRACE_ALL_LOOPS(W,C)
#endif
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop. Later, the calling routine
** should invoke sqlite3WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 155850 155851 155852 155853 155854 155855 155856 155857 155858 155859 155860 155861 155862 155863 155864 155865 155866 155867 155868 155869 155870 155871 155872 155873 155874 155875 155876 155877 155878 155879 155880 155881 155882 155883 155884 155885 155886 155887 155888 155889 155890 155891 155892 155893 155894 155895 155896 155897 155898 155899 155900 155901 155902 155903 155904 155905 155906 155907 155908 155909 155910 155911 155912 155913 155914 155915 155916 155917 155918 155919 155920 155921 155922 155923 155924 155925 155926 155927 155928 155929 155930 155931 155932 155933 155934 155935 155936 155937 155938 155939 155940 155941 155942 155943 155944 155945 155946 155947 155948 155949 155950 155951 155952 155953 155954 155955 155956 155957 155958 155959 155960 155961 155962 155963 155964 155965 155966 155967 155968 155969 155970 155971 155972 155973 155974 155975 155976 155977 155978 155979 155980 155981 155982 155983 155984 155985 155986 155987 155988 155989 155990 155991 155992 155993 155994 155995 155996 155997 155998 155999 156000 156001 156002 156003 156004 156005 156006 156007 |
}
}
}
# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C)
#else
# define WHERETRACE_ALL_LOOPS(W,C)
#endif
/* Attempt to omit tables from a join that do not affect the result.
** For a table to not affect the result, the following must be true:
**
** 1) The query must not be an aggregate.
** 2) The table must be the RHS of a LEFT JOIN.
** 3) Either the query must be DISTINCT, or else the ON or USING clause
** must contain a constraint that limits the scan of the table to
** at most a single row.
** 4) The table must not be referenced by any part of the query apart
** from its own USING or ON clause.
**
** For example, given:
**
** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
**
** then table t2 can be omitted from the following:
**
** SELECT v1, v3 FROM t1
** LEFT JOIN t2 ON (t1.ipk=t2.ipk)
** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
**
** or from:
**
** SELECT DISTINCT v1, v3 FROM t1
** LEFT JOIN t2
** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
*/
static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
WhereInfo *pWInfo,
Bitmask notReady
){
int i;
Bitmask tabUsed;
/* Preconditions checked by the caller */
assert( pWInfo->nLevel>=2 );
assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) );
/* These two preconditions checked by the caller combine to guarantee
** condition (1) of the header comment */
assert( pWInfo->pResultSet!=0 );
assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) );
tabUsed = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet);
if( pWInfo->pOrderBy ){
tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy);
}
for(i=pWInfo->nLevel-1; i>=1; i--){
WhereTerm *pTerm, *pEnd;
SrcItem *pItem;
WhereLoop *pLoop;
pLoop = pWInfo->a[i].pWLoop;
pItem = &pWInfo->pTabList->a[pLoop->iTab];
if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
&& (pLoop->wsFlags & WHERE_ONEROW)==0
){
continue;
}
if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|| pTerm->pExpr->iRightJoinTable!=pItem->iCursor
){
break;
}
}
}
if( pTerm<pEnd ) continue;
WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
notReady &= ~pLoop->maskSelf;
for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
pTerm->wtFlags |= TERM_CODED;
}
}
if( i!=pWInfo->nLevel-1 ){
int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
}
pWInfo->nLevel--;
assert( pWInfo->nLevel>0 );
}
return notReady;
}
/*
** Check to see if there are any SEARCH loops that might benefit from
** using a Bloom filter. Consider a Bloom filter if:
**
** (1) The SEARCH happens more than N times where N is the number
** of rows in the table that is being considered for the Bloom
** filter.
** (2) Some searches are expected to find zero rows. (This is determined
** by the WHERE_SELFCULL flag on the term.)
** (3) Bloom-filter processing is not disabled. (Checked by the
** caller.)
** (4) The size of the table being searched is known by ANALYZE.
**
** This block of code merely checks to see if a Bloom filter would be
** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the
** WhereLoop. The implementation of the Bloom filter comes further
** down where the code for each WhereLoop is generated.
*/
static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
const WhereInfo *pWInfo
){
int i;
LogEst nSearch;
assert( pWInfo->nLevel>=2 );
assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) );
nSearch = pWInfo->a[0].pWLoop->nOut;
for(i=1; i<pWInfo->nLevel; i++){
WhereLoop *pLoop = pWInfo->a[i].pWLoop;
const int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
if( (pLoop->wsFlags & reqFlags)==reqFlags
/* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
&& ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
){
SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
Table *pTab = pItem->pTab;
pTab->tabFlags |= TF_StatsUsed;
if( nSearch > pTab->nRowLogEst
&& (pTab->tabFlags & TF_HasStat1)!=0
){
testcase( pItem->fg.jointype & JT_LEFT );
pLoop->wsFlags |= WHERE_BLOOMFILTER;
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
WHERETRACE(0xffff, (
"-> use Bloom-filter on loop %c because there are ~%.1e "
"lookups into %s which has only ~%.1e rows\n",
pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
(double)sqlite3LogEstToInt(pTab->nRowLogEst)));
}
}
nSearch += pLoop->nOut;
}
}
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop. Later, the calling routine
** should invoke sqlite3WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
|
| ︙ | ︙ | |||
154733 154734 154735 154736 154737 154738 154739 | memset(&sWLB, 0, sizeof(sWLB)); /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; sWLB.pOrderBy = pOrderBy; | < < < < < < | 156125 156126 156127 156128 156129 156130 156131 156132 156133 156134 156135 156136 156137 156138 |
memset(&sWLB, 0, sizeof(sWLB));
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
sWLB.pOrderBy = pOrderBy;
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
*/
testcase( pTabList->nSrc==BMS );
if( pTabList->nSrc>BMS ){
sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
return 0;
|
| ︙ | ︙ | |||
154785 154786 154787 154788 154789 154790 154791 154792 154793 154794 154795 154796 154797 154798 154799 154800 154801 154802 154803 |
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
memset(&pWInfo->nOBSat, 0,
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet;
sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC;
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
whereLoopInit(sWLB.pNew);
#ifdef SQLITE_DEBUG
sWLB.pNew->cId = '*';
#endif
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
| > > > > < | > > | 156171 156172 156173 156174 156175 156176 156177 156178 156179 156180 156181 156182 156183 156184 156185 156186 156187 156188 156189 156190 156191 156192 156193 156194 156195 156196 156197 156198 156199 156200 156201 156202 156203 156204 156205 156206 156207 156208 156209 156210 |
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
memset(&pWInfo->nOBSat, 0,
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet;
pMaskSet->n = 0;
pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be
** a valid cursor number, to avoid an initial
** test for pMaskSet->n==0 in sqlite3WhereGetMask() */
sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC;
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
whereLoopInit(sWLB.pNew);
#ifdef SQLITE_DEBUG
sWLB.pNew->cId = '*';
#endif
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
/* Special case: No FROM clause
*/
if( nTabList==0 ){
if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0
&& OptimizationEnabled(db, SQLITE_DistinctOpt)
){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
}else{
/* Assign a bit from the bitmask to every term in the FROM clause.
**
** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
|
| ︙ | ︙ | |||
154856 154857 154858 154859 154860 154861 154862 | ** Do not do this if the expression contains non-deterministic functions ** that are not within a sub-select. This is not strictly required, but ** preserves SQLite's legacy behaviour in the following two cases: ** ** FROM ... WHERE random()>0; -- eval random() once per row ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall */ | | > > > > > | | 156247 156248 156249 156250 156251 156252 156253 156254 156255 156256 156257 156258 156259 156260 156261 156262 156263 156264 156265 156266 156267 156268 156269 156270 156271 156272 156273 156274 156275 156276 |
** Do not do this if the expression contains non-deterministic functions
** that are not within a sub-select. This is not strictly required, but
** preserves SQLite's legacy behaviour in the following two cases:
**
** FROM ... WHERE random()>0; -- eval random() once per row
** FROM ... WHERE (SELECT random())>0; -- eval random() once overall
*/
for(ii=0; ii<sWLB.pWC->nBase; ii++){
WhereTerm *pT = &sWLB.pWC->a[ii];
if( pT->wtFlags & TERM_VIRTUAL ) continue;
if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL);
pT->wtFlags |= TERM_CODED;
}
}
if( wctrlFlags & WHERE_WANT_DISTINCT ){
if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
wctrlFlags &= ~WHERE_WANT_DISTINCT;
pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT;
}else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
/* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){
/* Try to ORDER BY the result set to make distinct processing easier */
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
pWInfo->pOrderBy = pResultSet;
}
|
| ︙ | ︙ | |||
154967 154968 154969 154970 154971 154972 154973 |
sqlite3DebugPrintf("\n");
for(ii=0; ii<pWInfo->nLevel; ii++){
sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
}
}
#endif
| | | | | | | | | < < < < < < < < < < < < < < < < < < < | | | < | < < < < < < < < < < | > > > | < < < < < > | < < < < < < < < < < < < < < < < | < | | | 156363 156364 156365 156366 156367 156368 156369 156370 156371 156372 156373 156374 156375 156376 156377 156378 156379 156380 156381 156382 156383 156384 156385 156386 156387 156388 156389 156390 156391 156392 156393 156394 156395 156396 156397 156398 156399 156400 156401 156402 156403 156404 156405 156406 |
sqlite3DebugPrintf("\n");
for(ii=0; ii<pWInfo->nLevel; ii++){
sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
}
}
#endif
/* Attempt to omit tables from a join that do not affect the result.
** See the comment on whereOmitNoopJoin() for further information.
**
** This query optimization is factored out into a separate "no-inline"
** procedure to keep the sqlite3WhereBegin() procedure from becoming
** too large. If sqlite3WhereBegin() becomes too large, that prevents
** some C-compiler optimizers from in-lining the
** sqlite3WhereCodeOneLoopStart() procedure, and it is important to
** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
*/
notReady = ~(Bitmask)0;
if( pWInfo->nLevel>=2
&& pResultSet!=0 /* these two combine to guarantee */
&& 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
notReady = whereOmitNoopJoin(pWInfo, notReady);
nTabList = pWInfo->nLevel;
assert( nTabList>0 );
}
/* Check to see if there are any SEARCH loops that might benefit from
** using a Bloom filter.
*/
if( pWInfo->nLevel>=2
&& OptimizationEnabled(db, SQLITE_BloomFilter)
){
whereCheckIfBloomFilterIsUseful(pWInfo);
}
#if defined(WHERETRACE_ENABLED)
if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n");
sqlite3WhereClausePrint(sWLB.pWC);
}
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
#endif
|
| ︙ | ︙ | |||
155230 155231 155232 155233 155234 155235 155236 155237 155238 155239 |
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
** program.
*/
for(ii=0; ii<nTabList; ii++){
int addrExplain;
int wsFlags;
pLevel = &pWInfo->a[ii];
wsFlags = pLevel->pWLoop->wsFlags;
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
| > > > < | | > > > > < | 156578 156579 156580 156581 156582 156583 156584 156585 156586 156587 156588 156589 156590 156591 156592 156593 156594 156595 156596 156597 156598 156599 156600 156601 156602 156603 156604 156605 |
/* Generate the code to do the search. Each iteration of the for
** loop below generates code for a single nested loop of the VM
** program.
*/
for(ii=0; ii<nTabList; ii++){
int addrExplain;
int wsFlags;
if( pParse->nErr ) goto whereBeginError;
pLevel = &pWInfo->a[ii];
wsFlags = pLevel->pWLoop->wsFlags;
if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
constructAutomaticIndex(pParse, &pWInfo->sWC,
&pTabList->a[pLevel->iFrom], notReady, pLevel);
#endif
}else{
constructBloomFilter(pWInfo, ii, pLevel, notReady);
}
if( db->mallocFailed ) goto whereBeginError;
}
addrExplain = sqlite3WhereExplainOneScan(
pParse, pTabList, pLevel, wctrlFlags
);
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady);
pWInfo->iContinue = pLevel->addrCont;
if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
|
| ︙ | ︙ | |||
155351 155352 155353 155354 155355 155356 155357 |
}
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
}else{
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
| | | 156704 156705 156706 156707 156708 156709 156710 156711 156712 156713 156714 156715 156716 156717 156718 |
}
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
#endif
}else{
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
|| pParse->db->mallocFailed );
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
|
| ︙ | ︙ | |||
155420 155421 155422 155423 155424 155425 155426 |
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
if( (ws & WHERE_IDX_ONLY)==0 ){
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
}
if( (ws & WHERE_INDEXED)
| | | | 156773 156774 156775 156776 156777 156778 156779 156780 156781 156782 156783 156784 156785 156786 156787 156788 156789 156790 |
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
if( (ws & WHERE_IDX_ONLY)==0 ){
assert( pLevel->iTabCur==pTabList->a[pLevel->iFrom].iCursor );
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
}
if( (ws & WHERE_INDEXED)
|| ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx)
){
if( ws & WHERE_MULTI_OR ){
Index *pIx = pLevel->u.pCoveringIdx;
int iDb = sqlite3SchemaToIndex(db, pIx->pSchema);
sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
|
| ︙ | ︙ | |||
155504 155505 155506 155507 155508 155509 155510 |
** directly. This loop scans all that code looking for opcodes
** that reference the table and converts them into opcodes that
** reference the index.
*/
if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
pIdx = pLoop->u.btree.pIndex;
}else if( pLoop->wsFlags & WHERE_MULTI_OR ){
| | | 156857 156858 156859 156860 156861 156862 156863 156864 156865 156866 156867 156868 156869 156870 156871 |
** directly. This loop scans all that code looking for opcodes
** that reference the table and converts them into opcodes that
** reference the index.
*/
if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
pIdx = pLoop->u.btree.pIndex;
}else if( pLoop->wsFlags & WHERE_MULTI_OR ){
pIdx = pLevel->u.pCoveringIdx;
}
if( pIdx
&& !db->mallocFailed
){
if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
last = iEnd;
}else{
|
| ︙ | ︙ | |||
156165 156166 156167 156168 156169 156170 156171 |
assert(0); /*NO_TEST*/
} /*NO_TEST*/
static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ }
/* Window functions that use all window interfaces: xStep, xFinal,
** xValue, and xInverse */
#define WINDOWFUNCALL(name,nArg,extra) { \
| | | | | 157518 157519 157520 157521 157522 157523 157524 157525 157526 157527 157528 157529 157530 157531 157532 157533 157534 157535 157536 157537 157538 157539 157540 157541 157542 157543 157544 157545 157546 157547 157548 157549 |
assert(0); /*NO_TEST*/
} /*NO_TEST*/
static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ }
/* Window functions that use all window interfaces: xStep, xFinal,
** xValue, and xInverse */
#define WINDOWFUNCALL(name,nArg,extra) { \
nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \
name ## InvFunc, name ## Name, {0} \
}
/* Window functions that are implemented using bytecode and thus have
** no-op routines for their methods */
#define WINDOWFUNCNOOP(name,nArg,extra) { \
nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
noopStepFunc, noopValueFunc, noopValueFunc, \
noopStepFunc, name ## Name, {0} \
}
/* Window functions that use all window interfaces: xStep, the
** same routine for xFinalize and xValue and which never call
** xInverse. */
#define WINDOWFUNCX(name,nArg,extra) { \
nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \
noopStepFunc, name ## Name, {0} \
}
/*
** Register those built-in window functions that are not also aggregates.
|
| ︙ | ︙ | |||
156525 156526 156527 156528 156529 156530 156531 |
pExpr->op2++;
}
return WRC_Continue;
}
static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
| > | | 157878 157879 157880 157881 157882 157883 157884 157885 157886 157887 157888 157889 157890 157891 157892 157893 |
pExpr->op2++;
}
return WRC_Continue;
}
static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3ErrorMsg(pWalker->pParse,
"misuse of aggregate: %s()", pExpr->u.zToken);
}
return WRC_Continue;
}
/*
** If the SELECT statement passed as the second argument does not invoke
|
| ︙ | ︙ | |||
156613 156614 156615 156616 156617 156618 156619 |
pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0);
/* Append the arguments passed to each window function to the
** sub-select expression list. Also allocate two registers for each
** window function - one for the accumulator, another for interim
** results. */
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
| > > | | 157967 157968 157969 157970 157971 157972 157973 157974 157975 157976 157977 157978 157979 157980 157981 157982 157983 |
pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy, 0);
/* Append the arguments passed to each window function to the
** sub-select expression list. Also allocate two registers for each
** window function - one for the accumulator, another for interim
** results. */
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
ExprList *pArgs;
assert( ExprUseXList(pWin->pOwner) );
pArgs = pWin->pOwner->x.pList;
if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pWin->bExprArgs = 1;
}else{
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pSublist = exprListAppendList(pParse, pSublist, pArgs, 0);
|
| ︙ | ︙ | |||
156680 156681 156682 156683 156684 156685 156686 |
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
sqlite3WalkSelect(&w, pSub);
}
}else{
sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
| | > > > > | 158036 158037 158038 158039 158040 158041 158042 158043 158044 158045 158046 158047 158048 158049 158050 158051 158052 158053 158054 |
w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
sqlite3WalkSelect(&w, pSub);
}
}else{
sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
/* Defer deleting the temporary table pTab because if an error occurred,
** there could still be references to that table embedded in the
** result-set or ORDER BY clause of the SELECT statement p. */
sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab);
}
if( rc ){
if( pParse->nErr==0 ){
assert( pParse->db->mallocFailed );
sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
}
|
| ︙ | ︙ | |||
157006 157007 157008 157009 157010 157011 157012 |
/* The inline versions of min() and max() require a single ephemeral
** table and 3 registers. The registers are used as follows:
**
** regApp+0: slot to copy min()/max() argument to for MakeRecord
** regApp+1: integer value used to ensure keys are unique
** regApp+2: output of MakeRecord
*/
| > > > | | | 158366 158367 158368 158369 158370 158371 158372 158373 158374 158375 158376 158377 158378 158379 158380 158381 158382 158383 158384 |
/* The inline versions of min() and max() require a single ephemeral
** table and 3 registers. The registers are used as follows:
**
** regApp+0: slot to copy min()/max() argument to for MakeRecord
** regApp+1: integer value used to ensure keys are unique
** regApp+2: output of MakeRecord
*/
ExprList *pList;
KeyInfo *pKeyInfo;
assert( ExprUseXList(pWin->pOwner) );
pList = pWin->pOwner->x.pList;
pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
pWin->csrApp = pParse->nTab++;
pWin->regApp = pParse->nMem+1;
pParse->nMem += 3;
if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
assert( pKeyInfo->aSortFlags[0]==0 );
pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
}
|
| ︙ | ︙ | |||
157095 157096 157097 157098 157099 157100 157101 |
}
/*
** Return the number of arguments passed to the window-function associated
** with the object passed as the only argument to this function.
*/
static int windowArgCount(Window *pWin){
| > > | | 158458 158459 158460 158461 158462 158463 158464 158465 158466 158467 158468 158469 158470 158471 158472 158473 158474 |
}
/*
** Return the number of arguments passed to the window-function associated
** with the object passed as the only argument to this function.
*/
static int windowArgCount(Window *pWin){
const ExprList *pList;
assert( ExprUseXList(pWin->pOwner) );
pList = pWin->pOwner->x.pList;
return (pList ? pList->nExpr : 0);
}
typedef struct WindowCodeArg WindowCodeArg;
typedef struct WindowCsrAndReg WindowCsrAndReg;
/*
|
| ︙ | ︙ | |||
157280 157281 157282 157283 157284 157285 157286 157287 157288 157289 157290 157291 157292 157293 157294 157295 157296 157297 157298 157299 157300 157301 157302 157303 157304 157305 157306 157307 157308 157309 157310 157311 157312 157313 157314 157315 157316 157317 157318 157319 157320 |
);
assert( bInverse==0 || bInverse==1 );
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
}else if( pFunc->xSFunc!=noopStepFunc ){
int addrIf = 0;
if( pWin->pFilter ){
int regTmp;
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
regTmp = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regTmp);
}
if( pWin->bExprArgs ){
int iOp = sqlite3VdbeCurrentAddr(v);
int iEnd;
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
pOp->p1 = csr;
}
}
}
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
assert( nArg>0 );
pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
| > > > | 158645 158646 158647 158648 158649 158650 158651 158652 158653 158654 158655 158656 158657 158658 158659 158660 158661 158662 158663 158664 158665 158666 158667 158668 158669 158670 158671 158672 158673 158674 158675 158676 158677 158678 158679 158680 158681 158682 158683 158684 158685 158686 158687 158688 |
);
assert( bInverse==0 || bInverse==1 );
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
}else if( pFunc->xSFunc!=noopStepFunc ){
int addrIf = 0;
if( pWin->pFilter ){
int regTmp;
assert( ExprUseXList(pWin->pOwner) );
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
regTmp = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, regTmp);
}
if( pWin->bExprArgs ){
int iOp = sqlite3VdbeCurrentAddr(v);
int iEnd;
assert( ExprUseXList(pWin->pOwner) );
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
pOp->p1 = csr;
}
}
}
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
assert( nArg>0 );
assert( ExprUseXList(pWin->pOwner) );
pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
|
| ︙ | ︙ | |||
157492 157493 157494 157495 157496 157497 157498 157499 157500 157501 157502 157503 157504 157505 |
windowFullScan(p);
}else{
Parse *pParse = p->pParse;
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pFunc;
if( pFunc->zName==nth_valueName
|| pFunc->zName==first_valueName
){
int csr = pWin->csrApp;
int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
| > | 158860 158861 158862 158863 158864 158865 158866 158867 158868 158869 158870 158871 158872 158873 158874 |
windowFullScan(p);
}else{
Parse *pParse = p->pParse;
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pFunc;
assert( ExprUseXList(pWin->pOwner) );
if( pFunc->zName==nth_valueName
|| pFunc->zName==first_valueName
){
int csr = pWin->csrApp;
int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
|
| ︙ | ︙ | |||
158841 158842 158843 158844 158845 158846 158847 |
/* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
p->affExpr = 0;
p->flags = EP_Leaf;
ExprClearVVAProperties(p);
p->iAgg = -1;
p->pLeft = p->pRight = 0;
| < > | | 160210 160211 160212 160213 160214 160215 160216 160217 160218 160219 160220 160221 160222 160223 160224 160225 160226 |
/* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
p->affExpr = 0;
p->flags = EP_Leaf;
ExprClearVVAProperties(p);
p->iAgg = -1;
p->pLeft = p->pRight = 0;
p->pAggInfo = 0;
memset(&p->x, 0, sizeof(p->x));
memset(&p->y, 0, sizeof(p->y));
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
if( sqlite3Isquote(p->u.zToken[0]) ){
|
| ︙ | ︙ | |||
158949 158950 158951 158952 158953 158954 158955 | #define TK_DATABASE 38 #define TK_DESC 39 #define TK_DETACH 40 #define TK_EACH 41 #define TK_FAIL 42 #define TK_OR 43 #define TK_AND 44 | < | | | > | 160318 160319 160320 160321 160322 160323 160324 160325 160326 160327 160328 160329 160330 160331 160332 160333 160334 160335 | #define TK_DATABASE 38 #define TK_DESC 39 #define TK_DETACH 40 #define TK_EACH 41 #define TK_FAIL 42 #define TK_OR 43 #define TK_AND 44 #define TK_MATCH 45 #define TK_LIKE_KW 46 #define TK_BETWEEN 47 #define TK_IS 48 #define TK_IN 49 #define TK_ISNULL 50 #define TK_NOTNULL 51 #define TK_NE 52 #define TK_EQ 53 #define TK_GT 54 #define TK_LE 55 |
| ︙ | ︙ | |||
159264 159265 159266 159267 159268 159269 159270 | ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 160633 160634 160635 160636 160637 160638 160639 160640 160641 160642 160643 160644 160645 160646 160647 160648 160649 160650 160651 160652 160653 160654 160655 160656 160657 160658 160659 160660 160661 160662 160663 160664 160665 160666 160667 160668 160669 160670 160671 160672 160673 160674 160675 160676 160677 160678 160679 160680 160681 160682 160683 160684 160685 160686 160687 160688 160689 160690 160691 160692 160693 160694 160695 160696 160697 160698 160699 160700 160701 160702 160703 160704 160705 160706 160707 160708 160709 160710 160711 160712 160713 160714 160715 160716 160717 160718 160719 160720 160721 160722 160723 160724 160725 160726 160727 160728 160729 160730 160731 160732 160733 160734 160735 160736 160737 160738 160739 160740 160741 160742 160743 160744 160745 160746 160747 160748 160749 160750 160751 160752 160753 160754 160755 160756 160757 160758 160759 160760 160761 160762 160763 160764 160765 160766 160767 160768 160769 160770 160771 160772 160773 160774 160775 160776 160777 160778 160779 160780 160781 160782 160783 160784 160785 160786 160787 160788 160789 160790 160791 160792 160793 160794 160795 160796 160797 160798 160799 160800 160801 160802 160803 160804 160805 160806 160807 160808 160809 160810 160811 160812 160813 160814 160815 160816 160817 160818 160819 160820 160821 160822 160823 160824 160825 160826 160827 160828 160829 160830 160831 160832 160833 160834 160835 160836 160837 160838 160839 160840 160841 160842 160843 160844 160845 160846 160847 160848 160849 160850 160851 160852 160853 160854 160855 160856 160857 160858 160859 160860 160861 160862 160863 160864 160865 160866 160867 160868 160869 160870 160871 160872 160873 160874 160875 160876 160877 160878 160879 160880 160881 160882 160883 160884 160885 160886 160887 160888 160889 160890 160891 160892 160893 160894 160895 160896 160897 160898 160899 160900 160901 160902 160903 160904 160905 160906 160907 160908 160909 160910 160911 160912 160913 160914 160915 160916 160917 160918 160919 160920 160921 160922 160923 160924 160925 160926 160927 160928 160929 160930 160931 160932 160933 160934 160935 160936 160937 160938 160939 160940 160941 160942 160943 160944 160945 160946 160947 160948 160949 160950 160951 160952 160953 160954 160955 160956 160957 160958 160959 160960 160961 160962 160963 160964 160965 160966 160967 160968 160969 160970 160971 160972 160973 160974 160975 160976 160977 160978 160979 160980 160981 160982 160983 160984 160985 160986 160987 160988 160989 160990 160991 160992 160993 160994 160995 160996 160997 160998 160999 161000 161001 161002 161003 161004 161005 161006 161007 161008 161009 161010 161011 161012 161013 161014 161015 161016 161017 161018 161019 161020 161021 161022 161023 161024 161025 161026 161027 161028 161029 161030 161031 161032 161033 161034 161035 161036 161037 161038 161039 161040 161041 161042 161043 161044 161045 161046 161047 161048 161049 161050 161051 161052 161053 161054 161055 161056 161057 161058 161059 161060 161061 161062 161063 161064 161065 161066 161067 161068 161069 161070 161071 161072 161073 161074 161075 161076 161077 161078 161079 161080 161081 161082 161083 161084 161085 161086 161087 161088 161089 161090 161091 161092 161093 161094 161095 161096 161097 161098 161099 161100 161101 161102 161103 161104 161105 161106 161107 161108 161109 161110 161111 161112 161113 161114 161115 161116 161117 161118 161119 161120 161121 161122 161123 161124 161125 161126 161127 161128 161129 161130 161131 161132 161133 161134 161135 161136 161137 161138 161139 161140 161141 161142 161143 161144 161145 161146 161147 161148 161149 161150 161151 161152 161153 161154 161155 161156 161157 161158 161159 161160 161161 161162 161163 161164 161165 161166 161167 161168 161169 161170 161171 161172 161173 161174 161175 161176 161177 161178 161179 161180 161181 161182 161183 |
** yy_shift_ofst[] For each state, the offset into yy_action for
** shifting terminals.
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
#define YY_ACTTAB_COUNT (2022)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 564, 115, 112, 220, 169, 199, 115, 112, 220, 564,
/* 10 */ 375, 1266, 564, 376, 564, 270, 1309, 1309, 406, 407,
/* 20 */ 1084, 199, 1513, 41, 41, 515, 489, 521, 558, 558,
/* 30 */ 558, 965, 41, 41, 395, 41, 41, 51, 51, 966,
/* 40 */ 296, 1269, 296, 122, 123, 1207, 1207, 1041, 113, 1044,
/* 50 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 564, 407,
/* 60 */ 275, 275, 275, 275, 1268, 115, 112, 220, 115, 112,
/* 70 */ 220, 1512, 846, 561, 516, 561, 115, 112, 220, 250,
/* 80 */ 217, 71, 71, 122, 123, 1207, 1207, 1041, 113, 1044,
/* 90 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 440, 440,
/* 100 */ 440, 1149, 119, 119, 119, 119, 118, 118, 117, 117,
/* 110 */ 117, 116, 442, 1183, 1149, 116, 442, 1149, 546, 513,
/* 120 */ 1548, 1554, 374, 213, 6, 169, 1154, 522, 1154, 407,
/* 130 */ 1556, 461, 373, 1554, 535, 99, 463, 332, 121, 121,
/* 140 */ 121, 121, 119, 119, 119, 119, 118, 118, 117, 117,
/* 150 */ 117, 116, 442, 122, 123, 1207, 1207, 1041, 113, 1044,
/* 160 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 1257, 1183,
/* 170 */ 1184, 1185, 243, 1064, 564, 502, 499, 498, 567, 124,
/* 180 */ 567, 1128, 1627, 344, 1627, 497, 119, 119, 119, 119,
/* 190 */ 118, 118, 117, 117, 117, 116, 442, 70, 70, 407,
/* 200 */ 121, 121, 121, 121, 114, 117, 117, 117, 116, 442,
/* 210 */ 474, 1469, 119, 119, 119, 119, 118, 118, 117, 117,
/* 220 */ 117, 116, 442, 122, 123, 1207, 1207, 1041, 113, 1044,
/* 230 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 407, 208,
/* 240 */ 539, 1548, 1424, 81, 339, 6, 342, 80, 119, 119,
/* 250 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 381,
/* 260 */ 1126, 442, 122, 123, 1207, 1207, 1041, 113, 1044, 1034,
/* 270 */ 1034, 120, 120, 121, 121, 121, 121, 262, 463, 332,
/* 280 */ 359, 1567, 119, 119, 119, 119, 118, 118, 117, 117,
/* 290 */ 117, 116, 442, 1231, 1, 1, 571, 2, 1235, 1573,
/* 300 */ 571, 2, 1235, 307, 1149, 141, 417, 307, 407, 141,
/* 310 */ 1183, 98, 1317, 489, 866, 531, 1317, 1149, 215, 512,
/* 320 */ 1149, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 330 */ 116, 442, 122, 123, 1207, 1207, 1041, 113, 1044, 1034,
/* 340 */ 1034, 120, 120, 121, 121, 121, 121, 275, 275, 1001,
/* 350 */ 1257, 275, 275, 1128, 1628, 1021, 1628, 137, 415, 1600,
/* 360 */ 561, 272, 1255, 950, 561, 1423, 1183, 1184, 1185, 1594,
/* 370 */ 866, 1012, 530, 315, 231, 1011, 317, 1276, 231, 119,
/* 380 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442,
/* 390 */ 1570, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 400 */ 116, 442, 330, 359, 1567, 564, 446, 1011, 1011, 1013,
/* 410 */ 446, 877, 564, 306, 555, 407, 447, 1021, 563, 346,
/* 420 */ 184, 118, 118, 117, 117, 117, 116, 442, 71, 71,
/* 430 */ 439, 438, 1126, 1012, 472, 71, 71, 1011, 205, 122,
/* 440 */ 123, 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120,
/* 450 */ 121, 121, 121, 121, 1304, 219, 1283, 1183, 407, 570,
/* 460 */ 1183, 1235, 503, 1477, 1304, 546, 307, 489, 141, 1011,
/* 470 */ 1011, 1013, 546, 140, 545, 1317, 1214, 382, 1214, 378,
/* 480 */ 950, 514, 122, 123, 1207, 1207, 1041, 113, 1044, 1034,
/* 490 */ 1034, 120, 120, 121, 121, 121, 121, 472, 119, 119,
/* 500 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 283,
/* 510 */ 275, 275, 1476, 1183, 1184, 1185, 1183, 1184, 1185, 417,
/* 520 */ 1183, 243, 541, 561, 502, 499, 498, 1001, 407, 478,
/* 530 */ 1183, 472, 870, 143, 497, 1549, 185, 231, 9, 6,
/* 540 */ 253, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 550 */ 116, 442, 122, 123, 1207, 1207, 1041, 113, 1044, 1034,
/* 560 */ 1034, 120, 120, 121, 121, 121, 121, 407, 372, 446,
/* 570 */ 363, 863, 288, 1183, 397, 1204, 1183, 1184, 1185, 931,
/* 580 */ 330, 458, 318, 526, 564, 541, 1183, 1184, 1185, 284,
/* 590 */ 1183, 122, 123, 1207, 1207, 1041, 113, 1044, 1034, 1034,
/* 600 */ 120, 120, 121, 121, 121, 121, 291, 71, 71, 275,
/* 610 */ 275, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 620 */ 116, 442, 561, 1031, 1031, 1042, 1183, 1045, 287, 1183,
/* 630 */ 1184, 1185, 1204, 137, 218, 542, 1541, 407, 363, 470,
/* 640 */ 431, 1167, 32, 363, 527, 350, 1183, 1184, 1185, 380,
/* 650 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 660 */ 442, 122, 123, 1207, 1207, 1041, 113, 1044, 1034, 1034,
/* 670 */ 120, 120, 121, 121, 121, 121, 407, 392, 1227, 1183,
/* 680 */ 1022, 1540, 1183, 1184, 1185, 1523, 149, 1307, 1307, 306,
/* 690 */ 555, 151, 1546, 361, 5, 564, 6, 3, 1035, 1542,
/* 700 */ 122, 123, 1207, 1207, 1041, 113, 1044, 1034, 1034, 120,
/* 710 */ 120, 121, 121, 121, 121, 411, 505, 83, 71, 71,
/* 720 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 730 */ 442, 1183, 426, 428, 1183, 1183, 1184, 1185, 191, 261,
/* 740 */ 278, 358, 508, 353, 507, 248, 407, 455, 137, 1539,
/* 750 */ 1006, 349, 363, 472, 1539, 302, 1228, 405, 281, 119,
/* 760 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442,
/* 770 */ 122, 123, 1207, 1207, 1041, 113, 1044, 1034, 1034, 120,
/* 780 */ 120, 121, 121, 121, 121, 407, 452, 1183, 1184, 1185,
/* 790 */ 1183, 1184, 1185, 275, 275, 269, 269, 489, 483, 1525,
/* 800 */ 148, 363, 480, 564, 306, 555, 561, 489, 561, 122,
/* 810 */ 123, 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120,
/* 820 */ 121, 121, 121, 121, 564, 886, 13, 13, 293, 119,
/* 830 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442,
/* 840 */ 1183, 420, 1316, 564, 98, 417, 199, 13, 13, 150,
/* 850 */ 306, 555, 1312, 322, 386, 407, 506, 478, 562, 400,
/* 860 */ 920, 920, 425, 1539, 887, 292, 71, 71, 119, 119,
/* 870 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 122,
/* 880 */ 123, 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120,
/* 890 */ 121, 121, 121, 121, 564, 1149, 1183, 1184, 1185, 407,
/* 900 */ 275, 275, 451, 303, 1089, 1089, 486, 448, 1149, 276,
/* 910 */ 276, 1149, 1539, 561, 319, 286, 321, 71, 71, 429,
/* 920 */ 451, 450, 561, 952, 101, 1207, 1207, 1041, 113, 1044,
/* 930 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 119, 119,
/* 940 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 1105,
/* 950 */ 1183, 1547, 564, 12, 437, 6, 329, 564, 834, 835,
/* 960 */ 836, 1629, 393, 547, 1106, 246, 245, 244, 1545, 1258,
/* 970 */ 413, 1521, 6, 1086, 310, 71, 71, 1086, 564, 1107,
/* 980 */ 13, 13, 119, 119, 119, 119, 118, 118, 117, 117,
/* 990 */ 117, 116, 442, 451, 104, 427, 537, 320, 275, 275,
/* 1000 */ 906, 13, 13, 520, 1482, 1105, 1183, 1184, 1185, 484,
/* 1010 */ 907, 561, 546, 564, 407, 536, 295, 478, 253, 200,
/* 1020 */ 1106, 548, 1482, 1484, 1160, 1409, 16, 16, 126, 557,
/* 1030 */ 413, 479, 311, 951, 407, 1107, 71, 71, 122, 123,
/* 1040 */ 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120, 121,
/* 1050 */ 121, 121, 121, 1204, 407, 544, 552, 314, 122, 123,
/* 1060 */ 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120, 121,
/* 1070 */ 121, 121, 121, 441, 144, 1160, 468, 146, 122, 111,
/* 1080 */ 1207, 1207, 1041, 113, 1044, 1034, 1034, 120, 120, 121,
/* 1090 */ 121, 121, 121, 247, 12, 1482, 422, 119, 119, 119,
/* 1100 */ 119, 118, 118, 117, 117, 117, 116, 442, 1183, 564,
/* 1110 */ 1204, 207, 404, 403, 858, 950, 294, 119, 119, 119,
/* 1120 */ 119, 118, 118, 117, 117, 117, 116, 442, 564, 30,
/* 1130 */ 564, 1409, 55, 55, 1599, 564, 895, 119, 119, 119,
/* 1140 */ 119, 118, 118, 117, 117, 117, 116, 442, 510, 1409,
/* 1150 */ 1409, 56, 56, 15, 15, 439, 438, 407, 13, 13,
/* 1160 */ 31, 1187, 412, 1211, 1183, 1184, 1185, 196, 1213, 306,
/* 1170 */ 555, 858, 462, 193, 926, 564, 1212, 489, 361, 925,
/* 1180 */ 1183, 564, 123, 1207, 1207, 1041, 113, 1044, 1034, 1034,
/* 1190 */ 120, 120, 121, 121, 121, 121, 1544, 1149, 43, 43,
/* 1200 */ 6, 1214, 423, 1214, 13, 13, 564, 219, 538, 494,
/* 1210 */ 1149, 108, 556, 1149, 4, 392, 1127, 434, 1187, 194,
/* 1220 */ 424, 485, 337, 1315, 414, 171, 1253, 1321, 559, 57,
/* 1230 */ 57, 564, 950, 564, 224, 247, 1183, 1184, 1185, 561,
/* 1240 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 1250 */ 442, 443, 564, 517, 13, 13, 44, 44, 275, 275,
/* 1260 */ 1409, 275, 275, 553, 1353, 529, 213, 549, 456, 543,
/* 1270 */ 465, 561, 564, 137, 561, 58, 58, 469, 405, 1222,
/* 1280 */ 405, 274, 217, 108, 556, 110, 4, 405, 275, 275,
/* 1290 */ 564, 1352, 1021, 564, 1228, 59, 59, 523, 106, 106,
/* 1300 */ 559, 561, 275, 275, 412, 107, 457, 443, 566, 565,
/* 1310 */ 564, 8, 1011, 60, 60, 561, 61, 61, 564, 965,
/* 1320 */ 349, 926, 305, 443, 84, 204, 925, 966, 564, 306,
/* 1330 */ 555, 435, 405, 62, 62, 553, 476, 105, 564, 103,
/* 1340 */ 464, 45, 45, 1203, 1011, 1011, 1013, 1014, 27, 533,
/* 1350 */ 564, 46, 46, 453, 532, 1572, 1171, 445, 1528, 564,
/* 1360 */ 279, 47, 47, 327, 1021, 390, 390, 389, 264, 387,
/* 1370 */ 106, 106, 843, 49, 49, 108, 556, 107, 4, 443,
/* 1380 */ 566, 565, 50, 50, 1011, 225, 564, 313, 564, 96,
/* 1390 */ 564, 228, 559, 524, 147, 312, 38, 1123, 564, 394,
/* 1400 */ 466, 328, 280, 98, 544, 564, 17, 564, 323, 63,
/* 1410 */ 63, 64, 64, 65, 65, 443, 1011, 1011, 1013, 1014,
/* 1420 */ 27, 14, 14, 289, 564, 227, 564, 553, 66, 66,
/* 1430 */ 128, 128, 477, 162, 564, 309, 135, 564, 1003, 277,
/* 1440 */ 252, 533, 564, 1501, 564, 418, 534, 67, 67, 52,
/* 1450 */ 52, 564, 1287, 226, 564, 1500, 1021, 68, 68, 208,
/* 1460 */ 69, 69, 106, 106, 1286, 53, 53, 157, 157, 107,
/* 1470 */ 873, 443, 566, 565, 158, 158, 1011, 76, 76, 564,
/* 1480 */ 357, 564, 108, 556, 471, 4, 252, 408, 885, 884,
/* 1490 */ 356, 564, 306, 555, 564, 473, 564, 252, 481, 559,
/* 1500 */ 564, 334, 54, 54, 72, 72, 564, 230, 1011, 1011,
/* 1510 */ 1013, 1014, 27, 564, 129, 129, 449, 73, 73, 130,
/* 1520 */ 130, 564, 443, 131, 131, 519, 564, 873, 564, 127,
/* 1530 */ 127, 333, 1071, 98, 553, 1349, 156, 156, 564, 495,
/* 1540 */ 347, 249, 98, 338, 155, 155, 892, 893, 533, 136,
/* 1550 */ 136, 134, 134, 532, 341, 1171, 445, 1587, 564, 279,
/* 1560 */ 343, 132, 132, 1021, 390, 390, 389, 264, 387, 106,
/* 1570 */ 106, 843, 564, 1067, 564, 249, 107, 564, 443, 566,
/* 1580 */ 565, 133, 133, 1011, 225, 1015, 313, 108, 556, 1071,
/* 1590 */ 4, 345, 968, 969, 312, 75, 75, 77, 77, 1300,
/* 1600 */ 74, 74, 564, 1132, 559, 564, 108, 556, 959, 4,
/* 1610 */ 252, 923, 1083, 110, 1083, 1011, 1011, 1013, 1014, 27,
/* 1620 */ 1082, 1285, 1082, 559, 227, 42, 42, 443, 48, 48,
/* 1630 */ 1284, 856, 162, 145, 924, 135, 110, 352, 362, 553,
/* 1640 */ 1340, 1361, 1015, 1408, 1336, 301, 443, 1561, 1347, 550,
/* 1650 */ 1414, 551, 226, 202, 1265, 1333, 1256, 1244, 553, 1243,
/* 1660 */ 490, 1245, 1580, 267, 11, 391, 210, 223, 1021, 1390,
/* 1670 */ 1395, 282, 365, 367, 106, 106, 930, 369, 454, 285,
/* 1680 */ 1383, 107, 325, 443, 566, 565, 408, 1021, 1011, 326,
/* 1690 */ 475, 306, 555, 106, 106, 100, 556, 500, 4, 1400,
/* 1700 */ 107, 1399, 443, 566, 565, 398, 1283, 1011, 214, 355,
/* 1710 */ 1473, 290, 559, 1472, 1583, 449, 554, 371, 331, 197,
/* 1720 */ 1011, 1011, 1013, 1014, 27, 198, 209, 385, 1222, 173,
/* 1730 */ 221, 256, 1520, 1518, 1219, 443, 79, 416, 206, 1011,
/* 1740 */ 1011, 1013, 1014, 27, 83, 279, 182, 553, 82, 167,
/* 1750 */ 390, 390, 389, 264, 387, 35, 1396, 843, 1478, 459,
/* 1760 */ 175, 177, 460, 493, 178, 179, 180, 233, 96, 396,
/* 1770 */ 225, 1402, 313, 1401, 36, 1404, 1021, 467, 186, 482,
/* 1780 */ 312, 399, 106, 106, 237, 1467, 89, 1489, 488, 107,
/* 1790 */ 239, 443, 566, 565, 268, 336, 1011, 190, 491, 340,
/* 1800 */ 240, 401, 1246, 241, 509, 1294, 430, 1303, 91, 877,
/* 1810 */ 227, 215, 1566, 1302, 1301, 1273, 1598, 432, 162, 518,
/* 1820 */ 1272, 135, 1597, 354, 402, 433, 1271, 1596, 1011, 1011,
/* 1830 */ 1013, 1014, 27, 1293, 299, 360, 300, 525, 226, 95,
/* 1840 */ 254, 255, 1344, 364, 436, 125, 544, 1552, 10, 1453,
/* 1850 */ 379, 1551, 102, 304, 97, 528, 34, 568, 1177, 263,
/* 1860 */ 265, 266, 569, 1241, 1236, 172, 409, 410, 159, 383,
/* 1870 */ 377, 366, 408, 1345, 1343, 368, 370, 306, 555, 1342,
/* 1880 */ 1326, 1325, 1368, 201, 384, 1367, 1505, 1506, 160, 1504,
/* 1890 */ 1503, 142, 161, 211, 212, 78, 830, 444, 203, 308,
/* 1900 */ 297, 449, 222, 1081, 139, 1079, 316, 174, 163, 1203,
/* 1910 */ 229, 176, 232, 909, 324, 1095, 164, 181, 165, 419,
/* 1920 */ 421, 183, 85, 86, 87, 88, 166, 1098, 235, 234,
/* 1930 */ 1094, 152, 18, 236, 335, 1087, 252, 1216, 487, 238,
/* 1940 */ 37, 187, 188, 845, 492, 356, 242, 348, 496, 189,
/* 1950 */ 90, 93, 19, 20, 168, 875, 501, 351, 92, 504,
/* 1960 */ 888, 153, 511, 1133, 1165, 154, 298, 1047, 94, 1134,
/* 1970 */ 39, 958, 216, 271, 273, 192, 953, 110, 1151, 251,
/* 1980 */ 1155, 21, 1159, 22, 1158, 1139, 1153, 33, 23, 24,
/* 1990 */ 540, 25, 195, 98, 26, 1062, 1048, 1046, 1050, 1104,
/* 2000 */ 7, 1103, 257, 258, 1051, 28, 40, 560, 1016, 857,
/* 2010 */ 109, 29, 919, 138, 259, 260, 170, 1589, 388, 1588,
/* 2020 */ 1173, 1172,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 192, 273, 274, 275, 192, 192, 273, 274, 275, 192,
/* 10 */ 218, 215, 192, 218, 192, 212, 234, 235, 205, 19,
/* 20 */ 11, 192, 294, 215, 216, 203, 192, 203, 209, 210,
/* 30 */ 211, 31, 215, 216, 205, 215, 216, 215, 216, 39,
/* 40 */ 227, 215, 229, 43, 44, 45, 46, 47, 48, 49,
/* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 192, 19,
/* 60 */ 238, 239, 238, 239, 215, 273, 274, 275, 273, 274,
/* 70 */ 275, 237, 21, 251, 252, 251, 273, 274, 275, 255,
/* 80 */ 256, 215, 216, 43, 44, 45, 46, 47, 48, 49,
/* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 209, 210,
/* 100 */ 211, 76, 102, 103, 104, 105, 106, 107, 108, 109,
/* 110 */ 110, 111, 112, 59, 89, 111, 112, 92, 252, 307,
/* 120 */ 308, 313, 314, 25, 312, 192, 86, 261, 88, 19,
/* 130 */ 313, 80, 315, 313, 314, 25, 127, 128, 54, 55,
/* 140 */ 56, 57, 102, 103, 104, 105, 106, 107, 108, 109,
/* 150 */ 110, 111, 112, 43, 44, 45, 46, 47, 48, 49,
/* 160 */ 50, 51, 52, 53, 54, 55, 56, 57, 192, 115,
/* 170 */ 116, 117, 118, 122, 192, 121, 122, 123, 202, 69,
/* 180 */ 204, 22, 23, 16, 25, 131, 102, 103, 104, 105,
/* 190 */ 106, 107, 108, 109, 110, 111, 112, 215, 216, 19,
/* 200 */ 54, 55, 56, 57, 58, 108, 109, 110, 111, 112,
/* 210 */ 192, 160, 102, 103, 104, 105, 106, 107, 108, 109,
/* 220 */ 110, 111, 112, 43, 44, 45, 46, 47, 48, 49,
/* 230 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 141,
/* 240 */ 307, 308, 272, 24, 77, 312, 79, 67, 102, 103,
/* 250 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 277,
/* 260 */ 101, 112, 43, 44, 45, 46, 47, 48, 49, 50,
/* 270 */ 51, 52, 53, 54, 55, 56, 57, 26, 127, 128,
/* 280 */ 310, 311, 102, 103, 104, 105, 106, 107, 108, 109,
/* 290 */ 110, 111, 112, 184, 185, 186, 187, 188, 189, 186,
/* 300 */ 187, 188, 189, 194, 76, 196, 192, 194, 19, 196,
/* 310 */ 59, 25, 203, 192, 59, 87, 203, 89, 164, 165,
/* 320 */ 92, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 330 */ 111, 112, 43, 44, 45, 46, 47, 48, 49, 50,
/* 340 */ 51, 52, 53, 54, 55, 56, 57, 238, 239, 73,
/* 350 */ 192, 238, 239, 22, 23, 100, 25, 81, 237, 229,
/* 360 */ 251, 23, 204, 25, 251, 272, 115, 116, 117, 214,
/* 370 */ 115, 116, 144, 192, 265, 120, 262, 222, 265, 102,
/* 380 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 390 */ 192, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 400 */ 111, 112, 126, 310, 311, 192, 297, 152, 153, 154,
/* 410 */ 297, 125, 192, 137, 138, 19, 295, 100, 192, 23,
/* 420 */ 22, 106, 107, 108, 109, 110, 111, 112, 215, 216,
/* 430 */ 106, 107, 101, 116, 192, 215, 216, 120, 149, 43,
/* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 450 */ 54, 55, 56, 57, 222, 117, 224, 59, 19, 187,
/* 460 */ 59, 189, 23, 282, 232, 252, 194, 192, 196, 152,
/* 470 */ 153, 154, 252, 72, 261, 203, 152, 248, 154, 250,
/* 480 */ 142, 261, 43, 44, 45, 46, 47, 48, 49, 50,
/* 490 */ 51, 52, 53, 54, 55, 56, 57, 192, 102, 103,
/* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 267,
/* 510 */ 238, 239, 237, 115, 116, 117, 115, 116, 117, 192,
/* 520 */ 59, 118, 192, 251, 121, 122, 123, 73, 19, 192,
/* 530 */ 59, 192, 23, 72, 131, 308, 22, 265, 22, 312,
/* 540 */ 24, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 550 */ 111, 112, 43, 44, 45, 46, 47, 48, 49, 50,
/* 560 */ 51, 52, 53, 54, 55, 56, 57, 19, 192, 297,
/* 570 */ 192, 23, 267, 59, 203, 59, 115, 116, 117, 108,
/* 580 */ 126, 127, 128, 192, 192, 192, 115, 116, 117, 262,
/* 590 */ 59, 43, 44, 45, 46, 47, 48, 49, 50, 51,
/* 600 */ 52, 53, 54, 55, 56, 57, 267, 215, 216, 238,
/* 610 */ 239, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 620 */ 111, 112, 251, 45, 46, 47, 59, 49, 291, 115,
/* 630 */ 116, 117, 116, 81, 192, 305, 306, 19, 192, 268,
/* 640 */ 19, 23, 22, 192, 252, 24, 115, 116, 117, 192,
/* 650 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 660 */ 112, 43, 44, 45, 46, 47, 48, 49, 50, 51,
/* 670 */ 52, 53, 54, 55, 56, 57, 19, 22, 23, 59,
/* 680 */ 23, 303, 115, 116, 117, 192, 240, 234, 235, 137,
/* 690 */ 138, 240, 308, 192, 22, 192, 312, 22, 120, 306,
/* 700 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
/* 710 */ 53, 54, 55, 56, 57, 197, 95, 150, 215, 216,
/* 720 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 730 */ 112, 59, 231, 112, 59, 115, 116, 117, 25, 118,
/* 740 */ 119, 120, 121, 122, 123, 124, 19, 243, 81, 303,
/* 750 */ 23, 130, 192, 192, 303, 252, 101, 253, 203, 102,
/* 760 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 770 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
/* 780 */ 53, 54, 55, 56, 57, 19, 119, 115, 116, 117,
/* 790 */ 115, 116, 117, 238, 239, 238, 239, 192, 280, 192,
/* 800 */ 240, 192, 284, 192, 137, 138, 251, 192, 251, 43,
/* 810 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 820 */ 54, 55, 56, 57, 192, 35, 215, 216, 267, 102,
/* 830 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 840 */ 59, 230, 237, 192, 25, 192, 192, 215, 216, 240,
/* 850 */ 137, 138, 237, 16, 200, 19, 66, 192, 133, 205,
/* 860 */ 135, 136, 230, 303, 74, 203, 215, 216, 102, 103,
/* 870 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 43,
/* 880 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 890 */ 54, 55, 56, 57, 192, 76, 115, 116, 117, 19,
/* 900 */ 238, 239, 192, 252, 126, 127, 128, 192, 89, 238,
/* 910 */ 239, 92, 303, 251, 77, 262, 79, 215, 216, 129,
/* 920 */ 210, 211, 251, 142, 158, 45, 46, 47, 48, 49,
/* 930 */ 50, 51, 52, 53, 54, 55, 56, 57, 102, 103,
/* 940 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 12,
/* 950 */ 59, 308, 192, 212, 252, 312, 291, 192, 7, 8,
/* 960 */ 9, 300, 301, 203, 27, 126, 127, 128, 308, 207,
/* 970 */ 208, 192, 312, 29, 192, 215, 216, 33, 192, 42,
/* 980 */ 215, 216, 102, 103, 104, 105, 106, 107, 108, 109,
/* 990 */ 110, 111, 112, 283, 158, 230, 66, 160, 238, 239,
/* 1000 */ 63, 215, 216, 192, 192, 12, 115, 116, 117, 65,
/* 1010 */ 73, 251, 252, 192, 19, 85, 230, 192, 24, 24,
/* 1020 */ 27, 261, 210, 211, 94, 192, 215, 216, 22, 207,
/* 1030 */ 208, 290, 192, 142, 19, 42, 215, 216, 43, 44,
/* 1040 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1050 */ 55, 56, 57, 59, 19, 144, 63, 192, 43, 44,
/* 1060 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1070 */ 55, 56, 57, 252, 163, 145, 114, 22, 43, 44,
/* 1080 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1090 */ 55, 56, 57, 45, 212, 283, 263, 102, 103, 104,
/* 1100 */ 105, 106, 107, 108, 109, 110, 111, 112, 59, 192,
/* 1110 */ 116, 149, 106, 107, 59, 25, 291, 102, 103, 104,
/* 1120 */ 105, 106, 107, 108, 109, 110, 111, 112, 192, 22,
/* 1130 */ 192, 192, 215, 216, 23, 192, 25, 102, 103, 104,
/* 1140 */ 105, 106, 107, 108, 109, 110, 111, 112, 108, 192,
/* 1150 */ 192, 215, 216, 215, 216, 106, 107, 19, 215, 216,
/* 1160 */ 53, 59, 114, 114, 115, 116, 117, 285, 119, 137,
/* 1170 */ 138, 116, 290, 230, 134, 192, 127, 192, 192, 139,
/* 1180 */ 59, 192, 44, 45, 46, 47, 48, 49, 50, 51,
/* 1190 */ 52, 53, 54, 55, 56, 57, 308, 76, 215, 216,
/* 1200 */ 312, 152, 263, 154, 215, 216, 192, 117, 87, 19,
/* 1210 */ 89, 19, 20, 92, 22, 22, 23, 231, 116, 230,
/* 1220 */ 263, 263, 237, 203, 298, 299, 203, 239, 36, 215,
/* 1230 */ 216, 192, 142, 192, 15, 45, 115, 116, 117, 251,
/* 1240 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 1250 */ 112, 59, 192, 203, 215, 216, 215, 216, 238, 239,
/* 1260 */ 192, 238, 239, 71, 192, 144, 25, 203, 243, 230,
/* 1270 */ 243, 251, 192, 81, 251, 215, 216, 243, 253, 60,
/* 1280 */ 253, 255, 256, 19, 20, 25, 22, 253, 238, 239,
/* 1290 */ 192, 192, 100, 192, 101, 215, 216, 19, 106, 107,
/* 1300 */ 36, 251, 238, 239, 114, 113, 192, 115, 116, 117,
/* 1310 */ 192, 47, 120, 215, 216, 251, 215, 216, 192, 31,
/* 1320 */ 130, 134, 243, 59, 148, 149, 139, 39, 192, 137,
/* 1330 */ 138, 263, 253, 215, 216, 71, 19, 157, 192, 159,
/* 1340 */ 128, 215, 216, 25, 152, 153, 154, 155, 156, 85,
/* 1350 */ 192, 215, 216, 268, 90, 0, 1, 2, 192, 192,
/* 1360 */ 5, 215, 216, 151, 100, 10, 11, 12, 13, 14,
/* 1370 */ 106, 107, 17, 215, 216, 19, 20, 113, 22, 115,
/* 1380 */ 116, 117, 215, 216, 120, 30, 192, 32, 192, 148,
/* 1390 */ 192, 24, 36, 115, 22, 40, 24, 23, 192, 25,
/* 1400 */ 128, 23, 99, 25, 144, 192, 22, 192, 192, 215,
/* 1410 */ 216, 215, 216, 215, 216, 59, 152, 153, 154, 155,
/* 1420 */ 156, 215, 216, 151, 192, 70, 192, 71, 215, 216,
/* 1430 */ 215, 216, 115, 78, 192, 132, 81, 192, 23, 22,
/* 1440 */ 25, 85, 192, 192, 192, 61, 90, 215, 216, 215,
/* 1450 */ 216, 192, 225, 98, 192, 192, 100, 215, 216, 141,
/* 1460 */ 215, 216, 106, 107, 225, 215, 216, 215, 216, 113,
/* 1470 */ 59, 115, 116, 117, 215, 216, 120, 215, 216, 192,
/* 1480 */ 120, 192, 19, 20, 23, 22, 25, 132, 119, 120,
/* 1490 */ 130, 192, 137, 138, 192, 23, 192, 25, 192, 36,
/* 1500 */ 192, 192, 215, 216, 215, 216, 192, 140, 152, 153,
/* 1510 */ 154, 155, 156, 192, 215, 216, 161, 215, 216, 215,
/* 1520 */ 216, 192, 59, 215, 216, 19, 192, 116, 192, 215,
/* 1530 */ 216, 23, 59, 25, 71, 192, 215, 216, 192, 23,
/* 1540 */ 23, 25, 25, 192, 215, 216, 7, 8, 85, 215,
/* 1550 */ 216, 215, 216, 90, 192, 1, 2, 140, 192, 5,
/* 1560 */ 192, 215, 216, 100, 10, 11, 12, 13, 14, 106,
/* 1570 */ 107, 17, 192, 23, 192, 25, 113, 192, 115, 116,
/* 1580 */ 117, 215, 216, 120, 30, 59, 32, 19, 20, 116,
/* 1590 */ 22, 192, 83, 84, 40, 215, 216, 215, 216, 192,
/* 1600 */ 215, 216, 192, 97, 36, 192, 19, 20, 23, 22,
/* 1610 */ 25, 23, 152, 25, 154, 152, 153, 154, 155, 156,
/* 1620 */ 152, 225, 154, 36, 70, 215, 216, 59, 215, 216,
/* 1630 */ 192, 23, 78, 25, 23, 81, 25, 192, 192, 71,
/* 1640 */ 257, 192, 116, 192, 192, 254, 59, 317, 192, 192,
/* 1650 */ 192, 235, 98, 241, 192, 254, 192, 192, 71, 192,
/* 1660 */ 287, 192, 192, 286, 242, 190, 213, 296, 100, 266,
/* 1670 */ 270, 244, 254, 254, 106, 107, 108, 254, 258, 258,
/* 1680 */ 266, 113, 292, 115, 116, 117, 132, 100, 120, 245,
/* 1690 */ 292, 137, 138, 106, 107, 19, 20, 219, 22, 270,
/* 1700 */ 113, 270, 115, 116, 117, 270, 224, 120, 228, 218,
/* 1710 */ 218, 245, 36, 218, 195, 161, 279, 258, 244, 248,
/* 1720 */ 152, 153, 154, 155, 156, 248, 242, 244, 60, 296,
/* 1730 */ 296, 140, 199, 199, 38, 59, 293, 199, 149, 152,
/* 1740 */ 153, 154, 155, 156, 150, 5, 22, 71, 293, 43,
/* 1750 */ 10, 11, 12, 13, 14, 269, 271, 17, 282, 18,
/* 1760 */ 233, 236, 199, 18, 236, 236, 236, 198, 148, 245,
/* 1770 */ 30, 271, 32, 271, 269, 233, 100, 245, 233, 199,
/* 1780 */ 40, 245, 106, 107, 198, 245, 157, 289, 62, 113,
/* 1790 */ 198, 115, 116, 117, 199, 288, 120, 22, 220, 199,
/* 1800 */ 198, 220, 199, 198, 114, 226, 64, 217, 22, 125,
/* 1810 */ 70, 164, 311, 217, 217, 217, 223, 24, 78, 304,
/* 1820 */ 219, 81, 223, 217, 220, 112, 217, 217, 152, 153,
/* 1830 */ 154, 155, 156, 226, 281, 220, 281, 143, 98, 114,
/* 1840 */ 199, 91, 260, 259, 82, 147, 144, 316, 22, 276,
/* 1850 */ 199, 316, 157, 278, 146, 145, 25, 201, 13, 193,
/* 1860 */ 193, 6, 191, 191, 191, 299, 302, 302, 206, 246,
/* 1870 */ 248, 259, 132, 260, 260, 259, 259, 137, 138, 260,
/* 1880 */ 249, 249, 264, 247, 245, 264, 212, 212, 206, 212,
/* 1890 */ 212, 221, 206, 213, 213, 212, 4, 3, 22, 162,
/* 1900 */ 221, 161, 15, 23, 16, 23, 138, 150, 129, 25,
/* 1910 */ 24, 141, 143, 20, 16, 1, 129, 141, 129, 61,
/* 1920 */ 37, 150, 53, 53, 53, 53, 129, 115, 140, 34,
/* 1930 */ 1, 5, 22, 114, 160, 68, 25, 75, 41, 140,
/* 1940 */ 24, 68, 114, 20, 19, 130, 124, 23, 67, 22,
/* 1950 */ 22, 148, 22, 22, 37, 59, 67, 24, 22, 96,
/* 1960 */ 28, 23, 22, 97, 23, 23, 67, 23, 25, 23,
/* 1970 */ 22, 115, 140, 23, 23, 22, 142, 25, 88, 34,
/* 1980 */ 75, 34, 75, 34, 93, 23, 86, 22, 34, 34,
/* 1990 */ 24, 34, 25, 25, 34, 23, 23, 23, 23, 23,
/* 2000 */ 44, 23, 25, 22, 11, 22, 22, 25, 23, 23,
/* 2010 */ 22, 22, 134, 23, 140, 140, 25, 140, 15, 140,
/* 2020 */ 1, 1, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2030 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2040 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2050 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2060 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2070 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2080 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2090 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2100 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2110 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2120 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2130 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2140 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2150 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2160 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2170 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2180 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2190 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318,
/* 2200 */ 318, 318, 318, 318, 318, 318,
};
#define YY_SHIFT_COUNT (571)
#define YY_SHIFT_MIN (0)
#define YY_SHIFT_MAX (2020)
static const unsigned short int yy_shift_ofst[] = {
/* 0 */ 1554, 1355, 1740, 1192, 1192, 552, 1264, 1356, 1463, 1587,
/* 10 */ 1587, 1587, 276, 0, 0, 180, 1015, 1587, 1587, 1587,
/* 20 */ 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587,
/* 30 */ 1049, 1049, 1121, 1121, 54, 667, 552, 552, 552, 552,
/* 40 */ 552, 40, 110, 219, 289, 396, 439, 509, 548, 618,
/* 50 */ 657, 727, 766, 836, 995, 1015, 1015, 1015, 1015, 1015,
/* 60 */ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015,
/* 70 */ 1015, 1015, 1015, 1035, 1015, 1138, 880, 880, 1568, 1587,
/* 80 */ 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587,
/* 90 */ 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587,
/* 100 */ 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587, 1587,
/* 110 */ 1587, 1587, 1587, 1676, 1587, 1587, 1587, 1587, 1587, 1587,
/* 120 */ 1587, 1587, 1587, 1587, 1587, 1587, 1587, 146, 84, 84,
/* 130 */ 84, 84, 84, 277, 315, 401, 97, 461, 251, 531,
/* 140 */ 531, 51, 1190, 531, 531, 324, 324, 531, 713, 713,
/* 150 */ 713, 713, 151, 154, 154, 4, 149, 2022, 2022, 621,
/* 160 */ 621, 621, 567, 398, 398, 398, 398, 937, 937, 228,
/* 170 */ 251, 159, 331, 531, 531, 531, 531, 531, 531, 531,
/* 180 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531,
/* 190 */ 531, 531, 531, 819, 819, 531, 9, 25, 25, 1102,
/* 200 */ 1102, 911, 1032, 2022, 2022, 2022, 2022, 2022, 2022, 2022,
/* 210 */ 255, 317, 317, 514, 403, 620, 471, 672, 781, 891,
/* 220 */ 675, 531, 531, 531, 531, 531, 531, 531, 531, 531,
/* 230 */ 531, 454, 531, 531, 531, 531, 531, 531, 531, 531,
/* 240 */ 531, 531, 531, 531, 790, 790, 790, 531, 531, 531,
/* 250 */ 338, 531, 531, 531, 516, 930, 531, 531, 993, 531,
/* 260 */ 531, 531, 531, 531, 531, 531, 531, 778, 944, 725,
/* 270 */ 994, 994, 994, 994, 1090, 725, 725, 1040, 1006, 951,
/* 280 */ 1219, 962, 1176, 98, 1278, 1176, 1278, 1317, 1241, 962,
/* 290 */ 962, 1241, 962, 98, 1317, 286, 1111, 1048, 1288, 1288,
/* 300 */ 1288, 1278, 1260, 1260, 1180, 1318, 1187, 1372, 1668, 1668,
/* 310 */ 1591, 1591, 1696, 1696, 1591, 1594, 1589, 1724, 1706, 1741,
/* 320 */ 1741, 1741, 1741, 1591, 1745, 1620, 1589, 1589, 1620, 1724,
/* 330 */ 1706, 1620, 1706, 1620, 1591, 1745, 1629, 1726, 1591, 1745,
/* 340 */ 1775, 1591, 1745, 1591, 1745, 1775, 1690, 1690, 1690, 1742,
/* 350 */ 1786, 1786, 1775, 1690, 1684, 1690, 1742, 1690, 1690, 1647,
/* 360 */ 1793, 1713, 1713, 1775, 1694, 1725, 1694, 1725, 1694, 1725,
/* 370 */ 1694, 1725, 1591, 1750, 1750, 1762, 1762, 1698, 1702, 1826,
/* 380 */ 1591, 1695, 1698, 1708, 1710, 1620, 1831, 1845, 1845, 1855,
/* 390 */ 1855, 1855, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022,
/* 400 */ 2022, 2022, 2022, 2022, 2022, 2022, 2022, 578, 837, 655,
/* 410 */ 1193, 167, 839, 1055, 1374, 1303, 1107, 1367, 1212, 1272,
/* 420 */ 1378, 1384, 1415, 1461, 1472, 1508, 1516, 1517, 1411, 1369,
/* 430 */ 1539, 1360, 1506, 1473, 1550, 1585, 1509, 1588, 1460, 1468,
/* 440 */ 1608, 1611, 1526, 1417, 1892, 1894, 1876, 1737, 1887, 1888,
/* 450 */ 1880, 1882, 1768, 1757, 1779, 1884, 1884, 1886, 1770, 1893,
/* 460 */ 1769, 1898, 1914, 1776, 1787, 1884, 1789, 1858, 1883, 1884,
/* 470 */ 1771, 1869, 1870, 1871, 1872, 1797, 1812, 1895, 1788, 1929,
/* 480 */ 1926, 1910, 1819, 1774, 1867, 1911, 1873, 1862, 1897, 1799,
/* 490 */ 1828, 1916, 1923, 1925, 1815, 1822, 1927, 1881, 1928, 1930,
/* 500 */ 1924, 1931, 1889, 1896, 1933, 1863, 1932, 1936, 1899, 1917,
/* 510 */ 1938, 1803, 1940, 1941, 1942, 1944, 1943, 1946, 1948, 1866,
/* 520 */ 1832, 1950, 1951, 1856, 1945, 1953, 1834, 1952, 1947, 1949,
/* 530 */ 1954, 1955, 1890, 1905, 1900, 1956, 1907, 1891, 1957, 1962,
/* 540 */ 1965, 1966, 1967, 1968, 1960, 1972, 1952, 1973, 1974, 1975,
/* 550 */ 1976, 1977, 1978, 1981, 1993, 1983, 1984, 1985, 1986, 1988,
/* 560 */ 1989, 1982, 1878, 1874, 1875, 1877, 1879, 1991, 1990, 2003,
/* 570 */ 2019, 2020,
};
#define YY_REDUCE_COUNT (406)
#define YY_REDUCE_MIN (-272)
#define YY_REDUCE_MAX (1686)
static const short yy_reduce_ofst[] = {
/* 0 */ 109, 113, 272, 760, -178, -176, -192, -183, -180, -134,
/* 10 */ 213, 220, 371, -208, -205, -272, -197, 611, 632, 765,
/* 20 */ 786, 392, 943, 989, 503, 651, 1039, -18, 702, 821,
/* 30 */ 710, 812, -188, -67, -187, 555, 662, 1020, 1023, 1050,
/* 40 */ 1064, -267, -267, -267, -267, -267, -267, -267, -267, -267,
/* 50 */ -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
/* 60 */ -267, -267, -267, -267, -267, -267, -267, -267, -267, -267,
/* 70 */ -267, -267, -267, -267, -267, -267, -267, -267, 811, 917,
/* 80 */ 936, 938, 983, 1014, 1041, 1060, 1080, 1098, 1101, 1118,
/* 90 */ 1126, 1136, 1146, 1158, 1167, 1194, 1196, 1198, 1206, 1213,
/* 100 */ 1215, 1232, 1234, 1242, 1245, 1250, 1252, 1259, 1262, 1287,
/* 110 */ 1289, 1299, 1302, 1304, 1308, 1314, 1321, 1329, 1334, 1336,
/* 120 */ 1346, 1366, 1380, 1382, 1385, 1410, 1413, -267, -267, -267,
/* 130 */ -267, -267, -267, -267, -267, 446, -267, 451, -24, 121,
/* 140 */ 560, 518, 232, 609, 330, -181, -111, 654, 557, 671,
/* 150 */ 557, 671, 882, -30, 93, -267, -267, -267, -267, 155,
/* 160 */ 155, 155, 181, 242, 305, 339, 561, -218, 453, 227,
/* 170 */ 158, 661, 661, -171, 114, 327, 653, -166, 275, 605,
/* 180 */ 615, 337, 833, 665, 939, 957, 825, 958, 985, 501,
/* 190 */ 986, 378, 1068, 384, 643, 393, 741, 660, 888, 762,
/* 200 */ 822, 229, 988, 926, 504, 1025, 1027, 1034, 1026, 1079,
/* 210 */ -204, -174, -151, 18, 130, 198, 226, 376, 391, 442,
/* 220 */ 457, 493, 607, 715, 779, 782, 840, 865, 1072, 1099,
/* 230 */ 1114, 1085, 1166, 1216, 1251, 1263, 1306, 1309, 1343, 1351,
/* 240 */ 1362, 1368, 1399, 1407, 1227, 1239, 1396, 1438, 1445, 1446,
/* 250 */ 1383, 1449, 1451, 1452, 1391, 1330, 1456, 1457, 1416, 1458,
/* 260 */ 226, 1462, 1464, 1465, 1467, 1469, 1470, 1373, 1377, 1412,
/* 270 */ 1401, 1418, 1419, 1423, 1383, 1412, 1412, 1422, 1453, 1475,
/* 280 */ 1371, 1400, 1403, 1427, 1420, 1414, 1421, 1390, 1444, 1429,
/* 290 */ 1431, 1466, 1435, 1474, 1398, 1478, 1480, 1482, 1491, 1492,
/* 300 */ 1495, 1459, 1471, 1477, 1437, 1483, 1484, 1519, 1433, 1434,
/* 310 */ 1533, 1534, 1443, 1455, 1538, 1476, 1485, 1486, 1527, 1525,
/* 320 */ 1528, 1529, 1530, 1563, 1569, 1524, 1500, 1502, 1532, 1505,
/* 330 */ 1542, 1536, 1545, 1540, 1580, 1586, 1498, 1507, 1595, 1592,
/* 340 */ 1578, 1600, 1602, 1603, 1605, 1581, 1590, 1596, 1597, 1579,
/* 350 */ 1593, 1599, 1604, 1598, 1601, 1606, 1607, 1609, 1610, 1501,
/* 360 */ 1515, 1553, 1555, 1615, 1582, 1584, 1613, 1612, 1614, 1616,
/* 370 */ 1619, 1617, 1641, 1531, 1535, 1618, 1621, 1631, 1622, 1573,
/* 380 */ 1651, 1575, 1632, 1636, 1623, 1639, 1656, 1666, 1667, 1671,
/* 390 */ 1672, 1673, 1564, 1565, 1566, 1662, 1674, 1675, 1677, 1678,
/* 400 */ 1682, 1670, 1679, 1680, 1681, 1683, 1686,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 1633, 1633, 1633, 1462, 1230, 1341, 1230, 1230, 1230, 1462,
/* 10 */ 1462, 1462, 1230, 1371, 1371, 1515, 1263, 1230, 1230, 1230,
/* 20 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1461, 1230, 1230,
/* 30 */ 1230, 1230, 1550, 1550, 1230, 1230, 1230, 1230, 1230, 1230,
/* 40 */ 1230, 1230, 1380, 1230, 1387, 1230, 1230, 1230, 1230, 1230,
|
| ︙ | ︙ | |||
159928 159929 159930 159931 159932 159933 159934 |
59, /* DATABASE => ID */
59, /* DESC => ID */
59, /* DETACH => ID */
59, /* EACH => ID */
59, /* FAIL => ID */
0, /* OR => nothing */
0, /* AND => nothing */
| < > | 161294 161295 161296 161297 161298 161299 161300 161301 161302 161303 161304 161305 161306 161307 161308 161309 161310 161311 |
59, /* DATABASE => ID */
59, /* DESC => ID */
59, /* DETACH => ID */
59, /* EACH => ID */
59, /* FAIL => ID */
0, /* OR => nothing */
0, /* AND => nothing */
59, /* MATCH => ID */
59, /* LIKE_KW => ID */
0, /* BETWEEN => nothing */
0, /* IS => nothing */
0, /* IN => nothing */
0, /* ISNULL => nothing */
0, /* NOTNULL => nothing */
0, /* NE => nothing */
0, /* EQ => nothing */
0, /* GT => nothing */
0, /* LE => nothing */
|
| ︙ | ︙ | |||
160118 160119 160120 160121 160122 160123 160124 160125 160126 | #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ yyStackEntry *yystackEnd; /* Last entry in the stack */ #endif }; typedef struct yyParser yyParser; #ifndef NDEBUG /* #include <stdio.h> */ | > < | 161484 161485 161486 161487 161488 161489 161490 161491 161492 161493 161494 161495 161496 161497 161498 161499 161500 | #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ yyStackEntry *yystackEnd; /* Last entry in the stack */ #endif }; typedef struct yyParser yyParser; /* #include <assert.h> */ #ifndef NDEBUG /* #include <stdio.h> */ static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG /* ** Turn parser tracing on by giving a stream to which to write the trace |
| ︙ | ︙ | |||
160200 160201 160202 160203 160204 160205 160206 | /* 38 */ "DATABASE", /* 39 */ "DESC", /* 40 */ "DETACH", /* 41 */ "EACH", /* 42 */ "FAIL", /* 43 */ "OR", /* 44 */ "AND", | | | | | | 161566 161567 161568 161569 161570 161571 161572 161573 161574 161575 161576 161577 161578 161579 161580 161581 161582 161583 | /* 38 */ "DATABASE", /* 39 */ "DESC", /* 40 */ "DETACH", /* 41 */ "EACH", /* 42 */ "FAIL", /* 43 */ "OR", /* 44 */ "AND", /* 45 */ "MATCH", /* 46 */ "LIKE_KW", /* 47 */ "BETWEEN", /* 48 */ "IS", /* 49 */ "IN", /* 50 */ "ISNULL", /* 51 */ "NOTNULL", /* 52 */ "NE", /* 53 */ "EQ", /* 54 */ "GT", /* 55 */ "LE", |
| ︙ | ︙ | |||
163869 163870 163871 163872 163873 163874 163875 |
while(1){ /* Exit by "break" */
assert( yypParser->yytos>=yypParser->yystack );
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
| < > | 165235 165236 165237 165238 165239 165240 165241 165242 165243 165244 165245 165246 165247 165248 165249 165250 |
while(1){ /* Exit by "break" */
assert( yypParser->yytos>=yypParser->yystack );
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
#ifndef NDEBUG
assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
if( yyTraceFILE ){
int yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
yyruleno, yyRuleName[yyruleno],
yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
|
| ︙ | ︙ | |||
165117 165118 165119 165120 165121 165122 165123 165124 165125 165126 165127 165128 165129 165130 | int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; | > | 166483 166484 166485 166486 166487 166488 166489 166490 166491 166492 166493 166494 166495 166496 166497 | int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ Parse *pParentParse = 0; /* Outer parse context, if any */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| ︙ | ︙ | |||
165152 165153 165154 165155 165156 165157 165158 |
return SQLITE_NOMEM_BKPT;
}
#endif
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->pVList==0 );
| | | 166519 166520 166521 166522 166523 166524 166525 166526 166527 166528 166529 166530 166531 166532 166533 |
return SQLITE_NOMEM_BKPT;
}
#endif
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->pVList==0 );
pParentParse = db->pParse;
db->pParse = pParse;
while( 1 ){
n = sqlite3GetToken((u8*)zSql, &tokenType);
mxSqlLen -= n;
if( mxSqlLen<0 ){
pParse->rc = SQLITE_TOOBIG;
break;
|
| ︙ | ︙ | |||
165267 165268 165269 165270 165271 165272 165273 |
*/
sqlite3DeleteTable(db, pParse->pNewTable);
}
if( !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
sqlite3DbFree(db, pParse->pVList);
| | < | 166634 166635 166636 166637 166638 166639 166640 166641 166642 166643 166644 166645 166646 166647 166648 |
*/
sqlite3DeleteTable(db, pParse->pNewTable);
}
if( !IN_RENAME_OBJECT ){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
sqlite3DbFree(db, pParse->pVList);
db->pParse = pParentParse;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
|
| ︙ | ︙ | |||
166937 166938 166939 166940 166941 166942 166943 |
/*
** Invoke the destructor function associated with FuncDef p, if any. Except,
** if this is not the last copy of the function, do not invoke it. Multiple
** copies of a single function are created when create_function() is called
** with SQLITE_ANY as the encoding.
*/
static void functionDestroy(sqlite3 *db, FuncDef *p){
| | > > | 168303 168304 168305 168306 168307 168308 168309 168310 168311 168312 168313 168314 168315 168316 168317 168318 168319 |
/*
** Invoke the destructor function associated with FuncDef p, if any. Except,
** if this is not the last copy of the function, do not invoke it. Multiple
** copies of a single function are created when create_function() is called
** with SQLITE_ANY as the encoding.
*/
static void functionDestroy(sqlite3 *db, FuncDef *p){
FuncDestructor *pDestructor;
assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
pDestructor = p->u.pDestructor;
if( pDestructor ){
pDestructor->nRef--;
if( pDestructor->nRef==0 ){
pDestructor->xDestroy(pDestructor->pUserData);
sqlite3DbFree(db, pDestructor);
}
}
|
| ︙ | ︙ | |||
167200 167201 167202 167203 167204 167205 167206 167207 167208 167209 167210 167211 167212 167213 |
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
sqlite3_mutex_leave(db->mutex);
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
assert( sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
| > > > | 168568 168569 168570 168571 168572 168573 168574 168575 168576 168577 168578 168579 168580 168581 168582 168583 168584 |
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
sqlite3_mutex_leave(db->mutex);
db->eOpenState = SQLITE_STATE_CLOSED;
sqlite3_mutex_free(db->mutex);
assert( sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
|
| ︙ | ︙ | |||
167254 167255 167256 167257 167258 167259 167260 |
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
| | | 168625 168626 168627 168628 168629 168630 168631 168632 168633 168634 168635 168636 168637 168638 168639 |
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
db->xRollbackCallback(db->pRollbackArg);
}
}
|
| ︙ | ︙ | |||
167618 167619 167620 167621 167622 167623 167624 |
void (*xStep)(sqlite3_context*,int,sqlite3_value **),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInverse)(sqlite3_context*,int,sqlite3_value **),
FuncDestructor *pDestructor
){
FuncDef *p;
| < | | 168989 168990 168991 168992 168993 168994 168995 168996 168997 168998 168999 169000 169001 169002 169003 169004 169005 169006 169007 169008 169009 169010 169011 169012 |
void (*xStep)(sqlite3_context*,int,sqlite3_value **),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInverse)(sqlite3_context*,int,sqlite3_value **),
FuncDestructor *pDestructor
){
FuncDef *p;
int extraFlags;
assert( sqlite3_mutex_held(db->mutex) );
assert( xValue==0 || xSFunc==0 );
if( zFunctionName==0 /* Must have a valid name */
|| (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */
|| ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */
|| ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */
|| (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
|| (255<sqlite3Strlen30(zFunctionName))
){
return SQLITE_MISUSE_BKPT;
}
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
|
| ︙ | ︙ | |||
168101 168102 168103 168104 168105 168106 168107 168108 168109 168110 168111 168112 168113 168114 | pRet = db->pPreUpdateArg; db->xPreUpdateCallback = xCallback; db->pPreUpdateArg = pArg; sqlite3_mutex_leave(db->mutex); return pRet; } #endif /* SQLITE_ENABLE_PREUPDATE_HOOK */ #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). ** Invoke sqlite3_wal_checkpoint if the number of frames in the log file ** is greater than sqlite3.pWalArg cast to an integer (the value configured by ** wal_autocheckpoint()). | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 169471 169472 169473 169474 169475 169476 169477 169478 169479 169480 169481 169482 169483 169484 169485 169486 169487 169488 169489 169490 169491 169492 169493 169494 169495 169496 169497 169498 169499 169500 169501 169502 169503 169504 169505 169506 169507 169508 169509 169510 169511 169512 |
pRet = db->pPreUpdateArg;
db->xPreUpdateCallback = xCallback;
db->pPreUpdateArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pRet;
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
/*
** Register a function to be invoked prior to each autovacuum that
** determines the number of pages to vacuum.
*/
SQLITE_API int sqlite3_autovacuum_pages(
sqlite3 *db, /* Attach the hook to this database */
unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
void *pArg, /* Argument to the function */
void (*xDestructor)(void*) /* Destructor for pArg */
){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
if( xDestructor ) xDestructor(pArg);
return SQLITE_MISUSE_BKPT;
}
#endif
sqlite3_mutex_enter(db->mutex);
if( db->xAutovacDestr ){
db->xAutovacDestr(db->pAutovacPagesArg);
}
db->xAutovacPages = xCallback;
db->pAutovacPagesArg = pArg;
db->xAutovacDestr = xDestructor;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_WAL
/*
** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint().
** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
** is greater than sqlite3.pWalArg cast to an integer (the value configured by
** wal_autocheckpoint()).
|
| ︙ | ︙ | |||
168624 168625 168626 168627 168628 168629 168630 168631 168632 168633 168634 168635 168636 168637 |
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
return -1;
}
oldLimit = db->aLimit[limitId];
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
}
db->aLimit[limitId] = newLimit;
}
return oldLimit; /* IMP: R-53341-35419 */
}
/*
| > > | 170022 170023 170024 170025 170026 170027 170028 170029 170030 170031 170032 170033 170034 170035 170036 170037 |
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
return -1;
}
oldLimit = db->aLimit[limitId];
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
}else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
newLimit = 1;
}
db->aLimit[limitId] = newLimit;
}
return oldLimit; /* IMP: R-53341-35419 */
}
/*
|
| ︙ | ︙ | |||
168895 168896 168897 168898 168899 168900 168901 |
/*
** This routine does the core work of extracting URI parameters from a
** database filename for the sqlite3_uri_parameter() interface.
*/
static const char *uriParameter(const char *zFilename, const char *zParam){
zFilename += sqlite3Strlen30(zFilename) + 1;
| | | 170295 170296 170297 170298 170299 170300 170301 170302 170303 170304 170305 170306 170307 170308 170309 |
/*
** This routine does the core work of extracting URI parameters from a
** database filename for the sqlite3_uri_parameter() interface.
*/
static const char *uriParameter(const char *zFilename, const char *zParam){
zFilename += sqlite3Strlen30(zFilename) + 1;
while( ALWAYS(zFilename!=0) && zFilename[0] ){
int x = strcmp(zFilename, zParam);
zFilename += sqlite3Strlen30(zFilename) + 1;
if( x==0 ) return zFilename;
zFilename += sqlite3Strlen30(zFilename) + 1;
}
return 0;
}
|
| ︙ | ︙ | |||
168955 168956 168957 168958 168959 168960 168961 | /* Remove harmful bits from the flags parameter ** ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were ** dealt with in the previous code block. Besides these, the only ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, | | | > | 170355 170356 170357 170358 170359 170360 170361 170362 170363 170364 170365 170366 170367 170368 170369 170370 170371 170372 170373 |
/* Remove harmful bits from the flags parameter
**
** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were
** dealt with in the previous code block. Besides these, the only
** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY,
** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved
** bits. Silently mask off all other flags.
*/
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_MAIN_DB |
SQLITE_OPEN_TEMP_DB |
SQLITE_OPEN_TRANSIENT_DB |
SQLITE_OPEN_MAIN_JOURNAL |
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_SUPER_JOURNAL |
|
| ︙ | ︙ | |||
168990 168991 168992 168993 168994 168995 168996 |
goto opendb_out;
}
if( isThreadsafe==0 ){
sqlite3MutexWarnOnContention(db->mutex);
}
}
sqlite3_mutex_enter(db->mutex);
| | | 170391 170392 170393 170394 170395 170396 170397 170398 170399 170400 170401 170402 170403 170404 170405 |
goto opendb_out;
}
if( isThreadsafe==0 ){
sqlite3MutexWarnOnContention(db->mutex);
}
}
sqlite3_mutex_enter(db->mutex);
db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff;
db->nDb = 2;
db->eOpenState = SQLITE_STATE_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
|
| ︙ | ︙ | |||
169222 169223 169224 169225 169226 169227 169228 |
opendb_out:
if( db ){
assert( db->mutex!=0 || isThreadsafe==0
|| sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
| | | | | 170623 170624 170625 170626 170627 170628 170629 170630 170631 170632 170633 170634 170635 170636 170637 170638 170639 170640 170641 170642 170643 170644 170645 170646 170647 170648 170649 170650 170651 170652 170653 |
opendb_out:
if( db ){
assert( db->mutex!=0 || isThreadsafe==0
|| sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
assert( db!=0 || (rc&0xff)==SQLITE_NOMEM );
if( (rc&0xff)==SQLITE_NOMEM ){
sqlite3_close(db);
db = 0;
}else if( rc!=SQLITE_OK ){
db->eOpenState = SQLITE_STATE_SICK;
}
*ppDb = db;
#ifdef SQLITE_ENABLE_SQLLOG
if( sqlite3GlobalConfig.xSqllog ){
/* Opening a db handle. Fourth parameter is passed 0. */
void *pArg = sqlite3GlobalConfig.pSqllogArg;
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
}
#endif
sqlite3_free_filename(zOpen);
return rc;
}
/*
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
|
| ︙ | ︙ | |||
170026 170027 170028 170029 170030 170031 170032 170033 |
**
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
** the schema to be reparsed the next time it is needed. This has the
** effect of erasing all imposter tables.
*/
case SQLITE_TESTCTRL_IMPOSTER: {
sqlite3 *db = va_arg(ap, sqlite3*);
sqlite3_mutex_enter(db->mutex);
| > | > > | | | | > | 171427 171428 171429 171430 171431 171432 171433 171434 171435 171436 171437 171438 171439 171440 171441 171442 171443 171444 171445 171446 171447 171448 171449 171450 |
**
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
** the schema to be reparsed the next time it is needed. This has the
** effect of erasing all imposter tables.
*/
case SQLITE_TESTCTRL_IMPOSTER: {
sqlite3 *db = va_arg(ap, sqlite3*);
int iDb;
sqlite3_mutex_enter(db->mutex);
iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
if( iDb>=0 ){
db->init.iDb = iDb;
db->init.busy = db->init.imposterTable = va_arg(ap,int);
db->init.newTnum = va_arg(ap,int);
if( db->init.busy==0 && db->init.newTnum>0 ){
sqlite3ResetAllSchemasOfConnection(db);
}
}
sqlite3_mutex_leave(db->mutex);
break;
}
#if defined(YYCOVERAGE)
/* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out)
|
| ︙ | ︙ | |||
170106 170107 170108 170109 170110 170111 170112 170113 170114 170115 170116 170117 170118 170119 |
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
**
** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
** of the id-th tuning parameter to *piValue. If "id" is between -1
** and -SQLITE_NTUNE, then write the current value of the (-id)-th
| > > > > > > > > > > > > > > > > > > > > | 171511 171512 171513 171514 171515 171516 171517 171518 171519 171520 171521 171522 171523 171524 171525 171526 171527 171528 171529 171530 171531 171532 171533 171534 171535 171536 171537 171538 171539 171540 171541 171542 171543 171544 |
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
** double fIn, // Input value
** int *pLogEst, // sqlite3LogEstFromDouble(fIn)
** u64 *pInt, // sqlite3LogEstToInt(*pLogEst)
** int *pLogEst2 // sqlite3LogEst(*pInt)
** );
**
** Test access for the LogEst conversion routines.
*/
case SQLITE_TESTCTRL_LOGEST: {
double rIn = va_arg(ap, double);
LogEst rLogEst = sqlite3LogEstFromDouble(rIn);
u64 iInt = sqlite3LogEstToInt(rLogEst);
va_arg(ap, int*)[0] = rLogEst;
va_arg(ap, u64*)[0] = iInt;
va_arg(ap, int*)[0] = sqlite3LogEst(iInt);
break;
}
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
/* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
**
** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
** of the id-th tuning parameter to *piValue. If "id" is between -1
** and -SQLITE_NTUNE, then write the current value of the (-id)-th
|
| ︙ | ︙ | |||
170243 170244 170245 170246 170247 170248 170249 |
/*
** Return a pointer to the name of Nth query parameter of the filename.
*/
SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N){
if( zFilename==0 || N<0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
| | | 171668 171669 171670 171671 171672 171673 171674 171675 171676 171677 171678 171679 171680 171681 171682 |
/*
** Return a pointer to the name of Nth query parameter of the filename.
*/
SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N){
if( zFilename==0 || N<0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( ALWAYS(zFilename) && zFilename[0] && (N--)>0 ){
zFilename += sqlite3Strlen30(zFilename) + 1;
zFilename += sqlite3Strlen30(zFilename) + 1;
}
return zFilename[0] ? zFilename : 0;
}
/*
|
| ︙ | ︙ | |||
170293 170294 170295 170296 170297 170298 170299 |
if( zFilename==0 ) return 0;
return databaseName(zFilename);
}
SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){
if( zFilename==0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
| | | 171718 171719 171720 171721 171722 171723 171724 171725 171726 171727 171728 171729 171730 171731 171732 |
if( zFilename==0 ) return 0;
return databaseName(zFilename);
}
SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){
if( zFilename==0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( ALWAYS(zFilename) && zFilename[0] ){
zFilename += sqlite3Strlen30(zFilename) + 1;
zFilename += sqlite3Strlen30(zFilename) + 1;
}
return zFilename + 1;
}
SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){
#ifdef SQLITE_OMIT_WAL
|
| ︙ | ︙ | |||
171597 171598 171599 171600 171601 171602 171603 | ** amalgamation. */ #ifndef SQLITE_AMALGAMATION /* ** Macros indicating that conditional expressions are always true or ** false. */ | | > > > | | | | | < < | | | 173022 173023 173024 173025 173026 173027 173028 173029 173030 173031 173032 173033 173034 173035 173036 173037 173038 173039 173040 173041 173042 173043 173044 173045 173046 173047 | ** amalgamation. */ #ifndef SQLITE_AMALGAMATION /* ** Macros indicating that conditional expressions are always true or ** false. */ #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif /* ** Internal types used by SQLite. */ typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ typedef short int i16; /* 2-byte (or larger) signed integer */ |
| ︙ | ︙ | |||
172066 172067 172068 172069 172070 172071 172072 172073 172074 172075 172076 172077 172078 172079 | char **, int, int, int, const char *, int, Fts3Expr **, char ** ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, sqlite3_tokenizer_cursor ** ); /* fts3_aux.c */ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); | > | 173492 173493 173494 173495 173496 173497 173498 173499 173500 173501 173502 173503 173504 173505 173506 | char **, int, int, int, const char *, int, Fts3Expr **, char ** ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); #ifdef SQLITE_TEST SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif SQLITE_PRIVATE void *sqlite3Fts3MallocZero(i64 nByte); SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, sqlite3_tokenizer_cursor ** ); /* fts3_aux.c */ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); |
| ︙ | ︙ | |||
172123 172124 172125 172126 172127 172128 172129 |
#endif
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
| < < < < < < < | 173550 173551 173552 173553 173554 173555 173556 173557 173558 173559 173560 173561 173562 173563 |
#endif
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
/*
** This variable is set to false when running tests for which the on disk
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
#ifdef SQLITE_DEBUG
|
| ︙ | ︙ | |||
177154 177155 177156 177157 177158 177159 177160 |
}
case FTSQUERY_OR: {
Fts3Expr *pLeft = pExpr->pLeft;
Fts3Expr *pRight = pExpr->pRight;
sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
| | | | 178574 178575 178576 178577 178578 178579 178580 178581 178582 178583 178584 178585 178586 178587 178588 178589 |
}
case FTSQUERY_OR: {
Fts3Expr *pLeft = pExpr->pLeft;
Fts3Expr *pRight = pExpr->pRight;
sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid );
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
fts3EvalNextRow(pCsr, pLeft, pRc);
}else if( pLeft->bEof || iCmp>0 ){
fts3EvalNextRow(pCsr, pRight, pRc);
}else{
fts3EvalNextRow(pCsr, pLeft, pRc);
|
| ︙ | ︙ | |||
177793 177794 177795 177796 177797 177798 177799 177800 177801 177802 177803 177804 177805 177806 |
int bEofSave = pNear->bEof;
fts3EvalRestart(pCsr, pNear, &rc);
while( rc==SQLITE_OK && !pNear->bEof ){
fts3EvalNextRow(pCsr, pNear, &rc);
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
}
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
}
if( bTreeEof ){
while( rc==SQLITE_OK && !pNear->bEof ){
fts3EvalNextRow(pCsr, pNear, &rc);
}
}
if( rc!=SQLITE_OK ) return rc;
| > > > | 179213 179214 179215 179216 179217 179218 179219 179220 179221 179222 179223 179224 179225 179226 179227 179228 179229 |
int bEofSave = pNear->bEof;
fts3EvalRestart(pCsr, pNear, &rc);
while( rc==SQLITE_OK && !pNear->bEof ){
fts3EvalNextRow(pCsr, pNear, &rc);
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
}
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
if( rc==SQLITE_OK && pNear->bEof!=bEofSave ){
rc = FTS_CORRUPT_VTAB;
}
}
if( bTreeEof ){
while( rc==SQLITE_OK && !pNear->bEof ){
fts3EvalNextRow(pCsr, pNear, &rc);
}
}
if( rc!=SQLITE_OK ) return rc;
|
| ︙ | ︙ | |||
178215 178216 178217 178218 178219 178220 178221 178222 178223 178224 178225 178226 178227 178228 |
return SQLITE_OK;
}
}
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
iCol = 0;
while( i<nDoclist ){
sqlite3_int64 v = 0;
i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
switch( eState ){
/* State 0. In this state the integer just read was a docid. */
| > | 179638 179639 179640 179641 179642 179643 179644 179645 179646 179647 179648 179649 179650 179651 179652 |
return SQLITE_OK;
}
}
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
iCol = 0;
rc = SQLITE_OK;
while( i<nDoclist ){
sqlite3_int64 v = 0;
i += sqlite3Fts3GetVarint(&aDoclist[i], &v);
switch( eState ){
/* State 0. In this state the integer just read was a docid. */
|
| ︙ | ︙ | |||
178258 178259 178260 178261 178262 178263 178264 178265 178266 178267 178268 178269 178270 178271 178272 |
pCsr->aStat[0].nOcc++;
}
break;
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
pCsr->aStat[iCol+1].nDoc++;
eState = 2;
break;
}
}
pCsr->iCol = 0;
| > > > > < | 179682 179683 179684 179685 179686 179687 179688 179689 179690 179691 179692 179693 179694 179695 179696 179697 179698 179699 179700 179701 179702 179703 179704 179705 179706 179707 |
pCsr->aStat[0].nOcc++;
}
break;
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
if( iCol<1 ){
rc = SQLITE_CORRUPT_VTAB;
break;
}
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
pCsr->aStat[iCol+1].nDoc++;
eState = 2;
break;
}
}
pCsr->iCol = 0;
}else{
pCsr->isEof = 1;
}
return rc;
}
/*
|
| ︙ | ︙ | |||
178595 178596 178597 178598 178599 178600 178601 | } /* ** Allocate nByte bytes of memory using sqlite3_malloc(). If successful, ** zero the memory before returning a pointer to it. If unsuccessful, ** return NULL. */ | | | 180022 180023 180024 180025 180026 180027 180028 180029 180030 180031 180032 180033 180034 180035 180036 |
}
/*
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
SQLITE_PRIVATE void *sqlite3Fts3MallocZero(sqlite3_int64 nByte){
void *pRet = sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
sqlite3_tokenizer *pTokenizer,
|
| ︙ | ︙ | |||
178676 178677 178678 178679 178680 178681 178682 |
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
| | | 180103 180104 180105 180106 180107 180108 180109 180110 180111 180112 180113 180114 180115 180116 180117 |
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
}else{
pRet->eType = FTSQUERY_PHRASE;
pRet->pPhrase = (Fts3Phrase *)&pRet[1];
pRet->pPhrase->nToken = 1;
pRet->pPhrase->iColumn = iCol;
|
| ︙ | ︙ | |||
178931 178932 178933 178934 178935 178936 178937 |
** the next byte must contain either whitespace, an open or close
** parenthesis, a quote character, or EOF.
*/
cNext = zInput[nKey];
if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
| | | 180358 180359 180360 180361 180362 180363 180364 180365 180366 180367 180368 180369 180370 180371 180372 |
** the next byte must contain either whitespace, an open or close
** parenthesis, a quote character, or EOF.
*/
cNext = zInput[nKey];
if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pRet ){
return SQLITE_NOMEM;
}
pRet->eType = pKey->eType;
pRet->nNear = nNear;
*ppExpr = pRet;
*pnConsumed = (int)((zInput - z) + nKey);
|
| ︙ | ︙ | |||
179110 179111 179112 179113 179114 179115 179116 |
if( p ){
int isPhrase;
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
| | | 180537 180538 180539 180540 180541 180542 180543 180544 180545 180546 180547 180548 180549 180550 180551 |
if( p ){
int isPhrase;
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
|
| ︙ | ︙ | |||
179144 179145 179146 179147 179148 179149 179150 |
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
| | | 180571 180572 180573 180574 180575 180576 180577 180578 180579 180580 180581 180582 180583 180584 180585 |
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
|
| ︙ | ︙ | |||
183374 183375 183376 183377 183378 183379 183380 |
Fts3HashElem *pElem = *(pReader->ppNextElem);
sqlite3_free(pReader->aNode);
pReader->aNode = 0;
if( pElem ){
char *aCopy;
PendingList *pList = (PendingList *)fts3HashData(pElem);
int nCopy = pList->nData+1;
| > > > > | > > > > > | > | 184801 184802 184803 184804 184805 184806 184807 184808 184809 184810 184811 184812 184813 184814 184815 184816 184817 184818 184819 184820 184821 184822 184823 184824 184825 184826 |
Fts3HashElem *pElem = *(pReader->ppNextElem);
sqlite3_free(pReader->aNode);
pReader->aNode = 0;
if( pElem ){
char *aCopy;
PendingList *pList = (PendingList *)fts3HashData(pElem);
int nCopy = pList->nData+1;
int nTerm = fts3HashKeysize(pElem);
if( (nTerm+1)>pReader->nTermAlloc ){
sqlite3_free(pReader->zTerm);
pReader->zTerm = (char*)sqlite3_malloc((nTerm+1)*2);
if( !pReader->zTerm ) return SQLITE_NOMEM;
pReader->nTermAlloc = (nTerm+1)*2;
}
memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
pReader->zTerm[nTerm] = '\0';
pReader->nTerm = nTerm;
aCopy = (char*)sqlite3_malloc(nCopy);
if( !aCopy ) return SQLITE_NOMEM;
memcpy(aCopy, pList->aData, nCopy);
pReader->nNode = pReader->nDoclist = nCopy;
pReader->aNode = pReader->aDoclist = aCopy;
pReader->ppNextElem++;
assert( pReader->aNode );
|
| ︙ | ︙ | |||
183628 183629 183630 183631 183632 183633 183634 |
/*
** Free all allocations associated with the iterator passed as the
** second argument.
*/
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
if( pReader ){
| < | < | 185065 185066 185067 185068 185069 185070 185071 185072 185073 185074 185075 185076 185077 185078 185079 |
/*
** Free all allocations associated with the iterator passed as the
** second argument.
*/
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
if( pReader ){
sqlite3_free(pReader->zTerm);
if( !fts3SegReaderIsRootOnly(pReader) ){
sqlite3_free(pReader->aNode);
}
sqlite3_blob_close(pReader->pBlob);
}
sqlite3_free(pReader);
}
|
| ︙ | ︙ | |||
185822 185823 185824 185825 185826 185827 185828 |
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
| | | 187257 187258 187259 187260 187261 187262 187263 187264 187265 187266 187267 187268 187269 187270 187271 |
}
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->term.n || nSuffix>p->nNode-p->iOff || nSuffix==0 ){
return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
p->term.n = nPrefix+nSuffix;
p->iOff += nSuffix;
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
return FTS_CORRUPT_VTAB;
|
| ︙ | ︙ | |||
186216 186217 186218 186219 186220 186221 186222 |
static int fts3TermCmp(
const char *zLhs, int nLhs, /* LHS of comparison */
const char *zRhs, int nRhs /* RHS of comparison */
){
int nCmp = MIN(nLhs, nRhs);
int res;
| > | > > > | 187651 187652 187653 187654 187655 187656 187657 187658 187659 187660 187661 187662 187663 187664 187665 187666 187667 187668 187669 |
static int fts3TermCmp(
const char *zLhs, int nLhs, /* LHS of comparison */
const char *zRhs, int nRhs /* RHS of comparison */
){
int nCmp = MIN(nLhs, nRhs);
int res;
if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){
res = memcmp(zLhs, zRhs, nCmp);
}else{
res = 0;
}
if( res==0 ) res = nLhs - nRhs;
return res;
}
/*
|
| ︙ | ︙ | |||
186860 186861 186862 186863 186864 186865 186866 |
sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
if( SQLITE_ROW==sqlite3_step(pSelect) ){
const char *aHint = sqlite3_column_blob(pSelect, 0);
int nHint = sqlite3_column_bytes(pSelect, 0);
if( aHint ){
blobGrowBuffer(pHint, nHint, &rc);
if( rc==SQLITE_OK ){
| | | 188299 188300 188301 188302 188303 188304 188305 188306 188307 188308 188309 188310 188311 188312 188313 |
sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT);
if( SQLITE_ROW==sqlite3_step(pSelect) ){
const char *aHint = sqlite3_column_blob(pSelect, 0);
int nHint = sqlite3_column_bytes(pSelect, 0);
if( aHint ){
blobGrowBuffer(pHint, nHint, &rc);
if( rc==SQLITE_OK ){
if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint);
pHint->n = nHint;
}
}
}
rc2 = sqlite3_reset(pSelect);
if( rc==SQLITE_OK ) rc = rc2;
}
|
| ︙ | ︙ | |||
187977 187978 187979 187980 187981 187982 187983 |
*/
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
+ sizeof(MatchinfoBuffer);
sqlite3_int64 nStr = strlen(zMatchinfo);
| | < | 189416 189417 189418 189419 189420 189421 189422 189423 189424 189425 189426 189427 189428 189429 189430 189431 |
*/
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
+ sizeof(MatchinfoBuffer);
sqlite3_int64 nStr = strlen(zMatchinfo);
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
if( pRet ){
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
+ sizeof(u32)*((int)nElem+1);
pRet->nElem = (int)nElem;
pRet->zMatchinfo = ((char*)pRet) + nByte;
memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1);
pRet->aRef[0] = 1;
|
| ︙ | ︙ | |||
188383 188384 188385 188386 188387 188388 188389 |
return rc;
}
/* Now that it is known how many phrases there are, allocate and zero
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
| | < | 189821 189822 189823 189824 189825 189826 189827 189828 189829 189830 189831 189832 189833 189834 189835 189836 189837 189838 |
return rc;
}
/* Now that it is known how many phrases there are, allocate and zero
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
sIter.aPhrase = (SnippetPhrase *)sqlite3Fts3MallocZero(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
/* Initialize the contents of the SnippetIter object. Then iterate through
** the set of phrases in the expression to populate the aPhrase[] array.
*/
sIter.pCsr = pCsr;
sIter.iCol = iCol;
sIter.nSnippet = nSnippet;
|
| ︙ | ︙ | |||
188951 188952 188953 188954 188955 188956 188957 |
/*
** Advance the iterator passed as an argument to the next position. Return
** 1 if the iterator is at EOF or if it now points to the start of the
** position list for the next column.
*/
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
| | > > | 190388 190389 190390 190391 190392 190393 190394 190395 190396 190397 190398 190399 190400 190401 190402 190403 190404 190405 190406 190407 |
/*
** Advance the iterator passed as an argument to the next position. Return
** 1 if the iterator is at EOF or if it now points to the start of the
** position list for the next column.
*/
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
char *pRead;
sqlite3_int64 iRead;
int rc = 0;
if( NEVER(pIter==0) ) return 1;
pRead = pIter->pRead;
pRead += sqlite3Fts3GetVarint(pRead, &iRead);
if( iRead==0 || iRead==1 ){
pRead = 0;
rc = 1;
}else{
pIter->iPos += (int)(iRead-2);
}
|
| ︙ | ︙ | |||
188988 188989 188990 188991 188992 188993 188994 | int iCol; int nToken = 0; int rc = SQLITE_OK; /* Allocate and populate the array of LcsIterator objects. The array ** contains one element for each matchable phrase in the query. **/ | | < | 190427 190428 190429 190430 190431 190432 190433 190434 190435 190436 190437 190438 190439 190440 190441 190442 |
int iCol;
int nToken = 0;
int rc = SQLITE_OK;
/* Allocate and populate the array of LcsIterator objects. The array
** contains one element for each matchable phrase in the query.
**/
aIter = sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase);
if( !aIter ) return SQLITE_NOMEM;
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
for(i=0; i<pInfo->nPhrase; i++){
LcsIterator *pIter = &aIter[i];
nToken -= pIter->pExpr->pPhrase->nToken;
pIter->iPosOffset = nToken;
}
|
| ︙ | ︙ | |||
189451 189452 189453 189454 189455 189456 189457 | assert( pCsr->isRequireSeek==0 ); /* Count the number of terms in the query */ rc = fts3ExprLoadDoclists(pCsr, 0, &nToken); if( rc!=SQLITE_OK ) goto offsets_out; /* Allocate the array of TermOffset iterators. */ | | | | < | > | 190889 190890 190891 190892 190893 190894 190895 190896 190897 190898 190899 190900 190901 190902 190903 190904 190905 190906 190907 190908 190909 190910 190911 190912 190913 190914 190915 190916 190917 190918 190919 190920 190921 190922 190923 190924 190925 190926 190927 190928 190929 190930 |
assert( pCsr->isRequireSeek==0 );
/* Count the number of terms in the query */
rc = fts3ExprLoadDoclists(pCsr, 0, &nToken);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
sCtx.aTerm = (TermOffset *)sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
}
sCtx.iDocid = pCsr->iPrevId;
sCtx.pCsr = pCsr;
/* Loop through the table columns, appending offset information to
** string-buffer res for each column.
*/
for(iCol=0; iCol<pTab->nColumn; iCol++){
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
const char *ZDUMMY; /* Dummy argument used with xNext() */
int NDUMMY = 0; /* Dummy argument used with xNext() */
int iStart = 0;
int iEnd = 0;
int iCurrent = 0;
const char *zDoc;
int nDoc;
/* Initialize the contents of sCtx.aTerm[] for column iCol. This
** operation may fail if the database contains corrupt records.
*/
sCtx.iCol = iCol;
sCtx.iTerm = 0;
rc = fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
if( rc!=SQLITE_OK ) goto offsets_out;
/* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
** If an OOM occurs while retrieving the data (this can happen if SQLite
** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
** to the caller.
*/
|
| ︙ | ︙ | |||
190476 190477 190478 190479 190480 190481 190482 190483 190484 190485 190486 190487 190488 190489 190490 | #ifndef SQLITE_AMALGAMATION /* Unsigned integer types. These are already defined in the sqliteInt.h, ** but the definitions need to be repeated for separate compilation. */ typedef sqlite3_uint64 u64; typedef unsigned int u32; typedef unsigned short int u16; typedef unsigned char u8; #endif /* Objects */ typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; typedef struct JsonParse JsonParse; /* An instance of this object represents a JSON string | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 191914 191915 191916 191917 191918 191919 191920 191921 191922 191923 191924 191925 191926 191927 191928 191929 191930 191931 191932 191933 191934 191935 191936 191937 191938 191939 191940 191941 191942 191943 191944 191945 191946 191947 191948 191949 191950 191951 191952 191953 191954 191955 | #ifndef SQLITE_AMALGAMATION /* Unsigned integer types. These are already defined in the sqliteInt.h, ** but the definitions need to be repeated for separate compilation. */ typedef sqlite3_uint64 u64; typedef unsigned int u32; typedef unsigned short int u16; typedef unsigned char u8; # if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 # endif # if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) # elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) # else # define ALWAYS(X) (X) # define NEVER(X) (X) # endif # define testcase(X) #endif #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else # define VVA(X) X #endif /* ** Some of the testcase() macros in this file are problematic for gcov ** in that they generate false-miss errors randomly. This is a gcov problem, ** not a problem in this case. But to work around it, we disable the ** problematic test cases for production builds. */ #define json_testcase(X) /* Objects */ typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; typedef struct JsonParse JsonParse; /* An instance of this object represents a JSON string |
| ︙ | ︙ | |||
190534 190535 190536 190537 190538 190539 190540 190541 190542 |
/* A single node of parsed JSON
*/
struct JsonNode {
u8 eType; /* One of the JSON_ type values */
u8 jnFlags; /* JNODE flags */
u32 n; /* Bytes of content, or number of sub-nodes */
union {
| > | | | | | | 191999 192000 192001 192002 192003 192004 192005 192006 192007 192008 192009 192010 192011 192012 192013 192014 192015 192016 192017 192018 192019 192020 |
/* A single node of parsed JSON
*/
struct JsonNode {
u8 eType; /* One of the JSON_ type values */
u8 jnFlags; /* JNODE flags */
u8 eU; /* Which union element to use */
u32 n; /* Bytes of content, or number of sub-nodes */
union {
const char *zJContent; /* 1: Content for INT, REAL, and STRING */
u32 iAppend; /* 2: More terms for ARRAY and OBJECT */
u32 iKey; /* 3: Key for ARRAY objects in json_tree() */
u32 iReplace; /* 4: Replacement content for JNODE_REPLACE */
JsonNode *pPatch; /* 5: Node chain of patch for JNODE_PATCH */
} u;
};
/* A completely parsed JSON string
*/
struct JsonParse {
u32 nNode; /* Number of slots of aNode[] used */
|
| ︙ | ︙ | |||
190818 190819 190820 190821 190822 190823 190824 190825 |
** the number of JsonNode objects that are encoded.
*/
static void jsonRenderNode(
JsonNode *pNode, /* The node to render */
JsonString *pOut, /* Write JSON here */
sqlite3_value **aReplace /* Replacement values */
){
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
| > | > > > > > > | 192284 192285 192286 192287 192288 192289 192290 192291 192292 192293 192294 192295 192296 192297 192298 192299 192300 192301 192302 192303 192304 192305 192306 192307 192308 192309 192310 192311 192312 192313 192314 192315 192316 192317 192318 192319 192320 192321 192322 192323 192324 192325 192326 192327 192328 192329 192330 192331 192332 192333 192334 192335 192336 192337 192338 192339 192340 192341 192342 192343 192344 192345 192346 192347 192348 192349 192350 192351 192352 192353 192354 192355 192356 192357 192358 192359 192360 192361 192362 192363 192364 192365 192366 192367 192368 192369 |
** the number of JsonNode objects that are encoded.
*/
static void jsonRenderNode(
JsonNode *pNode, /* The node to render */
JsonString *pOut, /* Write JSON here */
sqlite3_value **aReplace /* Replacement values */
){
assert( pNode!=0 );
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){
assert( pNode->eU==4 );
jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
return;
}
assert( pNode->eU==5 );
pNode = pNode->u.pPatch;
}
switch( pNode->eType ){
default: {
assert( pNode->eType==JSON_NULL );
jsonAppendRaw(pOut, "null", 4);
break;
}
case JSON_TRUE: {
jsonAppendRaw(pOut, "true", 4);
break;
}
case JSON_FALSE: {
jsonAppendRaw(pOut, "false", 5);
break;
}
case JSON_STRING: {
if( pNode->jnFlags & JNODE_RAW ){
assert( pNode->eU==1 );
jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
break;
}
/* no break */ deliberate_fall_through
}
case JSON_REAL:
case JSON_INT: {
assert( pNode->eU==1 );
jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
break;
}
case JSON_ARRAY: {
u32 j = 1;
jsonAppendChar(pOut, '[');
for(;;){
while( j<=pNode->n ){
if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
jsonAppendSeparator(pOut);
jsonRenderNode(&pNode[j], pOut, aReplace);
}
j += jsonNodeSize(&pNode[j]);
}
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
assert( pNode->eU==2 );
pNode = &pNode[pNode->u.iAppend];
j = 1;
}
jsonAppendChar(pOut, ']');
break;
}
case JSON_OBJECT: {
u32 j = 1;
jsonAppendChar(pOut, '{');
for(;;){
while( j<=pNode->n ){
if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
jsonAppendSeparator(pOut);
jsonRenderNode(&pNode[j], pOut, aReplace);
jsonAppendChar(pOut, ':');
jsonRenderNode(&pNode[j+1], pOut, aReplace);
}
j += 1 + jsonNodeSize(&pNode[j+1]);
}
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
assert( pNode->eU==2 );
pNode = &pNode[pNode->u.iAppend];
j = 1;
}
jsonAppendChar(pOut, '}');
break;
}
}
|
| ︙ | ︙ | |||
190962 190963 190964 190965 190966 190967 190968 |
}
case JSON_FALSE: {
sqlite3_result_int(pCtx, 0);
break;
}
case JSON_INT: {
sqlite3_int64 i = 0;
| | > > | 192435 192436 192437 192438 192439 192440 192441 192442 192443 192444 192445 192446 192447 192448 192449 192450 192451 |
}
case JSON_FALSE: {
sqlite3_result_int(pCtx, 0);
break;
}
case JSON_INT: {
sqlite3_int64 i = 0;
const char *z;
assert( pNode->eU==1 );
z = pNode->u.zJContent;
if( z[0]=='-' ){ z++; }
while( z[0]>='0' && z[0]<='9' ){
unsigned v = *(z++) - '0';
if( i>=LARGEST_INT64/10 ){
if( i>LARGEST_INT64/10 ) goto int_as_real;
if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
if( v==9 ) goto int_as_real;
|
| ︙ | ︙ | |||
190990 190991 190992 190993 190994 190995 190996 |
int_done:
break;
int_as_real: ; /* no break */ deliberate_fall_through
}
case JSON_REAL: {
double r;
#ifdef SQLITE_AMALGAMATION
| | > > > > > | > > | 192465 192466 192467 192468 192469 192470 192471 192472 192473 192474 192475 192476 192477 192478 192479 192480 192481 192482 192483 192484 192485 192486 192487 192488 192489 192490 192491 192492 192493 192494 192495 192496 192497 192498 192499 192500 192501 192502 192503 192504 192505 192506 192507 192508 192509 192510 192511 192512 192513 192514 |
int_done:
break;
int_as_real: ; /* no break */ deliberate_fall_through
}
case JSON_REAL: {
double r;
#ifdef SQLITE_AMALGAMATION
const char *z;
assert( pNode->eU==1 );
z = pNode->u.zJContent;
sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
#else
assert( pNode->eU==1 );
r = strtod(pNode->u.zJContent, 0);
#endif
sqlite3_result_double(pCtx, r);
break;
}
case JSON_STRING: {
#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
** json_insert() and json_replace() and those routines do not
** call jsonReturn() */
if( pNode->jnFlags & JNODE_RAW ){
assert( pNode->eU==1 );
sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
SQLITE_TRANSIENT);
}else
#endif
assert( (pNode->jnFlags & JNODE_RAW)==0 );
if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
/* JSON formatted without any backslash-escapes */
assert( pNode->eU==1 );
sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
SQLITE_TRANSIENT);
}else{
/* Translate JSON formatted string into raw text */
u32 i;
u32 n = pNode->n;
const char *z;
char *zOut;
u32 j;
assert( pNode->eU==1 );
z = pNode->u.zJContent;
zOut = sqlite3_malloc( n+1 );
if( zOut==0 ){
sqlite3_result_error_nomem(pCtx);
break;
}
for(i=1, j=0; i<n-1; i++){
char c = z[i];
|
| ︙ | ︙ | |||
191139 191140 191141 191142 191143 191144 191145 |
static int jsonParseAddNode(
JsonParse *pParse, /* Append the node to this object */
u32 eType, /* Node type */
u32 n, /* Content size or sub-node count */
const char *zContent /* Content */
){
JsonNode *p;
| | > | 192621 192622 192623 192624 192625 192626 192627 192628 192629 192630 192631 192632 192633 192634 192635 192636 192637 192638 192639 192640 192641 |
static int jsonParseAddNode(
JsonParse *pParse, /* Append the node to this object */
u32 eType, /* Node type */
u32 n, /* Content size or sub-node count */
const char *zContent /* Content */
){
JsonNode *p;
if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){
return jsonParseAddNodeExpand(pParse, eType, n, zContent);
}
p = &pParse->aNode[pParse->nNode];
p->eType = (u8)eType;
p->jnFlags = 0;
VVA( p->eU = zContent ? 1 : 0 );
p->n = n;
p->u.zJContent = zContent;
return pParse->nNode++;
}
/*
** Return true if z[] begins with 4 (or more) hexadecimal digits
|
| ︙ | ︙ | |||
191212 191213 191214 191215 191216 191217 191218 191219 191220 191221 191222 191223 191224 191225 |
}
pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
return j+1;
}else if( c=='[' ){
/* Parse array */
iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
if( iThis<0 ) return -1;
for(j=i+1;;j++){
while( safe_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
if( x<0 ){
if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
| > | 192695 192696 192697 192698 192699 192700 192701 192702 192703 192704 192705 192706 192707 192708 192709 |
}
pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
return j+1;
}else if( c=='[' ){
/* Parse array */
iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
if( iThis<0 ) return -1;
memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u));
for(j=i+1;;j++){
while( safe_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
if( x<0 ){
if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
|
| ︙ | ︙ | |||
191476 191477 191478 191479 191480 191481 191482 191483 191484 191485 191486 191487 191488 191489 |
}
/*
** Compare the OBJECT label at pNode against zKey,nKey. Return true on
** a match.
*/
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
if( pNode->jnFlags & JNODE_RAW ){
if( pNode->n!=nKey ) return 0;
return strncmp(pNode->u.zJContent, zKey, nKey)==0;
}else{
if( pNode->n!=nKey+2 ) return 0;
return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
}
| > | 192960 192961 192962 192963 192964 192965 192966 192967 192968 192969 192970 192971 192972 192973 192974 |
}
/*
** Compare the OBJECT label at pNode against zKey,nKey. Return true on
** a match.
*/
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
assert( pNode->eU==1 );
if( pNode->jnFlags & JNODE_RAW ){
if( pNode->n!=nKey ) return 0;
return strncmp(pNode->u.zJContent, zKey, nKey)==0;
}else{
if( pNode->n!=nKey+2 ) return 0;
return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
}
|
| ︙ | ︙ | |||
191541 191542 191543 191544 191545 191546 191547 191548 191549 191550 191551 191552 191553 191554 191555 191556 191557 191558 191559 191560 191561 191562 191563 191564 191565 191566 191567 191568 191569 191570 |
if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
}
j++;
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
}
if( pApnd ){
u32 iStart, iLabel;
JsonNode *pNode;
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
zPath += i;
pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
}
return pNode;
}
}else if( zPath[0]=='[' ){
i = 0;
j = 1;
| > > > | 193026 193027 193028 193029 193030 193031 193032 193033 193034 193035 193036 193037 193038 193039 193040 193041 193042 193043 193044 193045 193046 193047 193048 193049 193050 193051 193052 193053 193054 193055 193056 193057 193058 |
if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
}
j++;
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
assert( pRoot->eU==2 );
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
}
if( pApnd ){
u32 iStart, iLabel;
JsonNode *pNode;
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
iLabel = jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
zPath += i;
pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
assert( pRoot->eU==0 );
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
VVA( pRoot->eU = 2 );
pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
}
return pNode;
}
}else if( zPath[0]=='[' ){
i = 0;
j = 1;
|
| ︙ | ︙ | |||
191579 191580 191581 191582 191583 191584 191585 191586 191587 191588 191589 191590 191591 191592 |
if( pRoot->eType!=JSON_ARRAY ) return 0;
for(;;){
while( j<=pBase->n ){
if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++;
j += jsonNodeSize(&pBase[j]);
}
if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
iBase += pBase->u.iAppend;
pBase = &pParse->aNode[iBase];
j = 1;
}
j = 2;
if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
unsigned int x = 0;
| > | 193067 193068 193069 193070 193071 193072 193073 193074 193075 193076 193077 193078 193079 193080 193081 |
if( pRoot->eType!=JSON_ARRAY ) return 0;
for(;;){
while( j<=pBase->n ){
if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++;
j += jsonNodeSize(&pBase[j]);
}
if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
assert( pBase->eU==2 );
iBase += pBase->u.iAppend;
pBase = &pParse->aNode[iBase];
j = 1;
}
j = 2;
if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
unsigned int x = 0;
|
| ︙ | ︙ | |||
191612 191613 191614 191615 191616 191617 191618 191619 191620 191621 191622 191623 191624 191625 191626 191627 191628 191629 191630 191631 191632 191633 191634 191635 191636 191637 191638 191639 191640 191641 191642 |
j = 1;
for(;;){
while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
}
if( j<=pRoot->n ){
return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
}
if( i==0 && pApnd ){
u32 iStart;
JsonNode *pNode;
iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
}
return pNode;
}
}else{
*pzErr = zPath;
}
return 0;
| > > > | 193101 193102 193103 193104 193105 193106 193107 193108 193109 193110 193111 193112 193113 193114 193115 193116 193117 193118 193119 193120 193121 193122 193123 193124 193125 193126 193127 193128 193129 193130 193131 193132 193133 193134 |
j = 1;
for(;;){
while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
assert( pRoot->eU==2 );
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
}
if( j<=pRoot->n ){
return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
}
if( i==0 && pApnd ){
u32 iStart;
JsonNode *pNode;
iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
assert( pRoot->eU==0 );
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
VVA( pRoot->eU = 2 );
}
return pNode;
}
}else{
*pzErr = zPath;
}
return 0;
|
| ︙ | ︙ | |||
191782 191783 191784 191785 191786 191787 191788 191789 191790 191791 191792 191793 191794 191795 191796 191797 191798 |
assert( x.aNode[i].eType==JSON_STRING );
zType = "label";
}else{
zType = jsonType[x.aNode[i].eType];
}
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
i, zType, x.aNode[i].n, x.aUp[i]);
if( x.aNode[i].u.zJContent!=0 ){
jsonAppendRaw(&s, " ", 1);
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
}
jsonAppendRaw(&s, "\n", 1);
}
jsonParseReset(&x);
jsonResult(&s);
}
| > > > > | 193274 193275 193276 193277 193278 193279 193280 193281 193282 193283 193284 193285 193286 193287 193288 193289 193290 193291 193292 193293 193294 |
assert( x.aNode[i].eType==JSON_STRING );
zType = "label";
}else{
zType = jsonType[x.aNode[i].eType];
}
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
i, zType, x.aNode[i].n, x.aUp[i]);
assert( x.aNode[i].eU==0 || x.aNode[i].eU==1 );
if( x.aNode[i].u.zJContent!=0 ){
assert( x.aNode[i].eU==1 );
jsonAppendRaw(&s, " ", 1);
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
}else{
assert( x.aNode[i].eU==0 );
}
jsonAppendRaw(&s, "\n", 1);
}
jsonParseReset(&x);
jsonResult(&s);
}
|
| ︙ | ︙ | |||
191967 191968 191969 191970 191971 191972 191973 191974 191975 191976 191977 191978 191979 191980 191981 191982 191983 191984 191985 191986 191987 191988 191989 191990 191991 191992 191993 191994 191995 191996 191997 191998 191999 192000 192001 192002 192003 192004 192005 192006 192007 192008 192009 192010 192011 192012 192013 192014 |
}
iRoot = iTarget;
for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
u32 nKey;
const char *zKey;
assert( pPatch[i].eType==JSON_STRING );
assert( pPatch[i].jnFlags & JNODE_LABEL );
nKey = pPatch[i].n;
zKey = pPatch[i].u.zJContent;
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
assert( pTarget[j].eType==JSON_STRING );
assert( pTarget[j].jnFlags & JNODE_LABEL );
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
if( pPatch[i+1].eType==JSON_NULL ){
pTarget[j+1].jnFlags |= JNODE_REMOVE;
}else{
JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
if( pNew==0 ) return 0;
pTarget = &pParse->aNode[iTarget];
if( pNew!=&pTarget[j+1] ){
pTarget[j+1].u.pPatch = pNew;
pTarget[j+1].jnFlags |= JNODE_PATCH;
}
}
break;
}
}
if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
int iStart, iPatch;
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
if( pParse->oom ) return 0;
jsonRemoveAllNulls(pPatch);
pTarget = &pParse->aNode[iTarget];
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
iRoot = iStart;
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
}
}
return pTarget;
}
| > > > > > > > > > > > > | 193463 193464 193465 193466 193467 193468 193469 193470 193471 193472 193473 193474 193475 193476 193477 193478 193479 193480 193481 193482 193483 193484 193485 193486 193487 193488 193489 193490 193491 193492 193493 193494 193495 193496 193497 193498 193499 193500 193501 193502 193503 193504 193505 193506 193507 193508 193509 193510 193511 193512 193513 193514 193515 193516 193517 193518 193519 193520 193521 193522 |
}
iRoot = iTarget;
for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
u32 nKey;
const char *zKey;
assert( pPatch[i].eType==JSON_STRING );
assert( pPatch[i].jnFlags & JNODE_LABEL );
assert( pPatch[i].eU==1 );
nKey = pPatch[i].n;
zKey = pPatch[i].u.zJContent;
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
assert( pTarget[j].eType==JSON_STRING );
assert( pTarget[j].jnFlags & JNODE_LABEL );
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
if( pPatch[i+1].eType==JSON_NULL ){
pTarget[j+1].jnFlags |= JNODE_REMOVE;
}else{
JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
if( pNew==0 ) return 0;
pTarget = &pParse->aNode[iTarget];
if( pNew!=&pTarget[j+1] ){
assert( pTarget[j+1].eU==0
|| pTarget[j+1].eU==1
|| pTarget[j+1].eU==2 );
testcase( pTarget[j+1].eU==1 );
testcase( pTarget[j+1].eU==2 );
VVA( pTarget[j+1].eU = 5 );
pTarget[j+1].u.pPatch = pNew;
pTarget[j+1].jnFlags |= JNODE_PATCH;
}
}
break;
}
}
if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
int iStart, iPatch;
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
if( pParse->oom ) return 0;
jsonRemoveAllNulls(pPatch);
pTarget = &pParse->aNode[iTarget];
assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 );
testcase( pParse->aNode[iRoot].eU==2 );
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
VVA( pParse->aNode[iRoot].eU = 2 );
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
iRoot = iStart;
assert( pParse->aNode[iPatch].eU==0 );
VVA( pParse->aNode[iPatch].eU = 5 );
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
}
}
return pTarget;
}
|
| ︙ | ︙ | |||
192142 192143 192144 192145 192146 192147 192148 192149 192150 192151 192152 192153 192154 192155 192156 192157 192158 192159 192160 |
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
assert( x.nNode );
for(i=1; i<(u32)argc; i+=2){
zPath = (const char*)sqlite3_value_text(argv[i]);
pNode = jsonLookup(&x, zPath, 0, ctx);
if( x.nErr ) goto replace_err;
if( pNode ){
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
replace_err:
jsonParseReset(&x);
}
| > > > > | 193650 193651 193652 193653 193654 193655 193656 193657 193658 193659 193660 193661 193662 193663 193664 193665 193666 193667 193668 193669 193670 193671 193672 |
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
assert( x.nNode );
for(i=1; i<(u32)argc; i+=2){
zPath = (const char*)sqlite3_value_text(argv[i]);
pNode = jsonLookup(&x, zPath, 0, ctx);
if( x.nErr ) goto replace_err;
if( pNode ){
assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
json_testcase( pNode->eU!=0 && pNode->eU!=1 );
pNode->jnFlags |= (u8)JNODE_REPLACE;
VVA( pNode->eU = 4 );
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
assert( x.aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
replace_err:
jsonParseReset(&x);
}
|
| ︙ | ︙ | |||
192196 192197 192198 192199 192200 192201 192202 192203 192204 192205 192206 192207 192208 192209 192210 192211 192212 192213 192214 |
pNode = jsonLookup(&x, zPath, &bApnd, ctx);
if( x.oom ){
sqlite3_result_error_nomem(ctx);
goto jsonSetDone;
}else if( x.nErr ){
goto jsonSetDone;
}else if( pNode && (bApnd || bIsSet) ){
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
jsonSetDone:
jsonParseReset(&x);
}
| > > > > | 193708 193709 193710 193711 193712 193713 193714 193715 193716 193717 193718 193719 193720 193721 193722 193723 193724 193725 193726 193727 193728 193729 193730 |
pNode = jsonLookup(&x, zPath, &bApnd, ctx);
if( x.oom ){
sqlite3_result_error_nomem(ctx);
goto jsonSetDone;
}else if( x.nErr ){
goto jsonSetDone;
}else if( pNode && (bApnd || bIsSet) ){
json_testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 );
assert( pNode->eU!=3 || pNode->eU!=5 );
VVA( pNode->eU = 4 );
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
assert( x.aNode[0].eU==4 );
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
}
jsonSetDone:
jsonParseReset(&x);
}
|
| ︙ | ︙ | |||
192551 192552 192553 192554 192555 192556 192557 192558 192559 192560 192561 192562 192563 192564 |
p->i++;
p->iRowid++;
if( p->i<p->iEnd ){
u32 iUp = p->sParse.aUp[p->i];
JsonNode *pUp = &p->sParse.aNode[iUp];
p->eType = pUp->eType;
if( pUp->eType==JSON_ARRAY ){
if( iUp==p->i-1 ){
pUp->u.iKey = 0;
}else{
pUp->u.iKey++;
}
}
}
| > > > | 194067 194068 194069 194070 194071 194072 194073 194074 194075 194076 194077 194078 194079 194080 194081 194082 194083 |
p->i++;
p->iRowid++;
if( p->i<p->iEnd ){
u32 iUp = p->sParse.aUp[p->i];
JsonNode *pUp = &p->sParse.aNode[iUp];
p->eType = pUp->eType;
if( pUp->eType==JSON_ARRAY ){
assert( pUp->eU==0 || pUp->eU==3 );
json_testcase( pUp->eU==3 );
VVA( pUp->eU = 3 );
if( iUp==p->i-1 ){
pUp->u.iKey = 0;
}else{
pUp->u.iKey++;
}
}
}
|
| ︙ | ︙ | |||
192597 192598 192599 192600 192601 192602 192603 192604 192605 192606 192607 192608 192609 192610 192611 192612 192613 192614 192615 192616 |
return;
}
iUp = p->sParse.aUp[i];
jsonEachComputePath(p, pStr, iUp);
pNode = &p->sParse.aNode[i];
pUp = &p->sParse.aNode[iUp];
if( pUp->eType==JSON_ARRAY ){
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
}
}
/* Return the value of a column */
static int jsonEachColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
| > > > | 194116 194117 194118 194119 194120 194121 194122 194123 194124 194125 194126 194127 194128 194129 194130 194131 194132 194133 194134 194135 194136 194137 194138 |
return;
}
iUp = p->sParse.aUp[i];
jsonEachComputePath(p, pStr, iUp);
pNode = &p->sParse.aNode[i];
pUp = &p->sParse.aNode[iUp];
if( pUp->eType==JSON_ARRAY ){
assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
testcase( pUp->eU==0 );
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
assert( pNode->eType==JSON_STRING );
assert( pNode->jnFlags & JNODE_LABEL );
assert( pNode->eU==1 );
jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
}
}
/* Return the value of a column */
static int jsonEachColumn(
sqlite3_vtab_cursor *cur, /* The cursor */
|
| ︙ | ︙ | |||
192624 192625 192626 192627 192628 192629 192630 192631 192632 192633 192634 192635 192636 192637 |
if( p->i==0 ) break;
if( p->eType==JSON_OBJECT ){
jsonReturn(pThis, ctx, 0);
}else if( p->eType==JSON_ARRAY ){
u32 iKey;
if( p->bRecursive ){
if( p->iRowid==0 ) break;
iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
}else{
iKey = p->iRowid;
}
sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
}
break;
| > | 194146 194147 194148 194149 194150 194151 194152 194153 194154 194155 194156 194157 194158 194159 194160 |
if( p->i==0 ) break;
if( p->eType==JSON_OBJECT ){
jsonReturn(pThis, ctx, 0);
}else if( p->eType==JSON_ARRAY ){
u32 iKey;
if( p->bRecursive ){
if( p->iRowid==0 ) break;
assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 );
iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
}else{
iKey = p->iRowid;
}
sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
}
break;
|
| ︙ | ︙ | |||
192673 192674 192675 192676 192677 192678 192679 192680 192681 192682 192683 192684 192685 192686 |
jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
}else{
jsonAppendChar(&x, '$');
}
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
}
}
jsonResult(&x);
break;
}
case JEACH_PATH: {
| > | 194196 194197 194198 194199 194200 194201 194202 194203 194204 194205 194206 194207 194208 194209 194210 |
jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
}else{
jsonAppendChar(&x, '$');
}
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
assert( pThis->eU==1 );
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
}
}
jsonResult(&x);
break;
}
case JEACH_PATH: {
|
| ︙ | ︙ | |||
192740 192741 192742 192743 192744 192745 192746 192747 192748 192749 192750 192751 192752 192753 |
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol;
int iMask;
if( pConstraint->iColumn < JEACH_JSON ) continue;
iCol = pConstraint->iColumn - JEACH_JSON;
assert( iCol==0 || iCol==1 );
iMask = 1 << iCol;
if( pConstraint->usable==0 ){
unusableMask |= iMask;
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
aIdx[iCol] = i;
idxMask |= iMask;
}
| > | 194264 194265 194266 194267 194268 194269 194270 194271 194272 194273 194274 194275 194276 194277 194278 |
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
int iCol;
int iMask;
if( pConstraint->iColumn < JEACH_JSON ) continue;
iCol = pConstraint->iColumn - JEACH_JSON;
assert( iCol==0 || iCol==1 );
testcase( iCol==0 );
iMask = 1 << iCol;
if( pConstraint->usable==0 ){
unusableMask |= iMask;
}else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
aIdx[iCol] = i;
idxMask |= iMask;
}
|
| ︙ | ︙ | |||
192837 192838 192839 192840 192841 192842 192843 192844 192845 192846 192847 192848 192849 192850 |
}
}else{
pNode = p->sParse.aNode;
}
p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
p->eType = pNode->eType;
if( p->eType>=JSON_ARRAY ){
pNode->u.iKey = 0;
p->iEnd = p->i + pNode->n + 1;
if( p->bRecursive ){
p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
p->i--;
}
| > > | 194362 194363 194364 194365 194366 194367 194368 194369 194370 194371 194372 194373 194374 194375 194376 194377 |
}
}else{
pNode = p->sParse.aNode;
}
p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
p->eType = pNode->eType;
if( p->eType>=JSON_ARRAY ){
assert( pNode->eU==0 );
VVA( pNode->eU = 3 );
pNode->u.iKey = 0;
p->iEnd = p->i + pNode->n + 1;
if( p->bRecursive ){
p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
p->i--;
}
|
| ︙ | ︙ | |||
193097 193098 193099 193100 193101 193102 193103 193104 193105 193106 193107 193108 193109 193110 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) # undef NDEBUG #endif #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) | > > > | 194624 194625 194626 194627 194628 194629 194630 194631 194632 194633 194634 194635 194636 194637 194638 194639 194640 | #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif #if defined(NDEBUG) && defined(SQLITE_DEBUG) # undef NDEBUG #endif #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) |
| ︙ | ︙ | |||
193448 193449 193450 193451 193452 193453 193454 | #endif #endif /* The testcase() macro should already be defined in the amalgamation. If ** it is not, make it a no-op. */ #ifndef SQLITE_AMALGAMATION | > > > > | > | 194978 194979 194980 194981 194982 194983 194984 194985 194986 194987 194988 194989 194990 194991 194992 194993 194994 194995 194996 194997 |
#endif
#endif
/* The testcase() macro should already be defined in the amalgamation. If
** it is not, make it a no-op.
*/
#ifndef SQLITE_AMALGAMATION
# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
unsigned int sqlite3RtreeTestcase = 0;
# define testcase(X) if( X ){ sqlite3RtreeTestcase += __LINE__; }
# else
# define testcase(X)
# endif
#endif
/*
** Make sure that the compiler intrinsics we desire are enabled when
** compiling with an appropriate version of MSVC unless prevented by
** the SQLITE_DISABLE_INTRINSIC define.
*/
|
| ︙ | ︙ | |||
194294 194295 194296 194297 194298 194299 194300 |
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
|| p->op==RTREE_FALSE );
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
switch( p->op ){
case RTREE_TRUE: return; /* Always satisfied */
case RTREE_FALSE: break; /* Never satisfied */
| < < | > > > > > > | | > > > > | > | 195829 195830 195831 195832 195833 195834 195835 195836 195837 195838 195839 195840 195841 195842 195843 195844 195845 195846 195847 195848 195849 195850 195851 195852 195853 195854 195855 195856 195857 195858 195859 195860 195861 195862 195863 195864 195865 |
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
|| p->op==RTREE_FALSE );
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
switch( p->op ){
case RTREE_TRUE: return; /* Always satisfied */
case RTREE_FALSE: break; /* Never satisfied */
case RTREE_EQ:
RTREE_DECODE_COORD(eInt, pCellData, val);
/* val now holds the lower bound of the coordinate pair */
if( p->u.rValue>=val ){
pCellData += 4;
RTREE_DECODE_COORD(eInt, pCellData, val);
/* val now holds the upper bound of the coordinate pair */
if( p->u.rValue<=val ) return;
}
break;
case RTREE_LE:
case RTREE_LT:
RTREE_DECODE_COORD(eInt, pCellData, val);
/* val now holds the lower bound of the coordinate pair */
if( p->u.rValue>=val ) return;
break;
default:
pCellData += 4;
RTREE_DECODE_COORD(eInt, pCellData, val);
/* val now holds the upper bound of the coordinate pair */
if( p->u.rValue<=val ) return;
break;
}
*peWithin = NOT_WITHIN;
}
/*
** Check the leaf RTree cell given by pCellData against constraint p.
** If this constraint is not satisfied, set *peWithin to NOT_WITHIN.
|
| ︙ | ︙ | |||
195212 195213 195214 195215 195216 195217 195218 |
sqlite3_int64 iBest = 0;
RtreeDValue fMinGrowth = RTREE_ZERO;
RtreeDValue fMinArea = RTREE_ZERO;
int nCell = NCELL(pNode);
RtreeCell cell;
| | | 196756 196757 196758 196759 196760 196761 196762 196763 196764 196765 196766 196767 196768 196769 196770 |
sqlite3_int64 iBest = 0;
RtreeDValue fMinGrowth = RTREE_ZERO;
RtreeDValue fMinArea = RTREE_ZERO;
int nCell = NCELL(pNode);
RtreeCell cell;
RtreeNode *pChild = 0;
RtreeCell *aCell = 0;
/* Select the child node which will be enlarged the least if pCell
** is inserted into it. Resolve ties by choosing the entry with
** the smallest area.
*/
|
| ︙ | ︙ | |||
195570 195571 195572 195573 195574 195575 195576 195577 195578 195579 195580 195581 195582 195583 |
}
if( pChild ){
nodeRelease(pRtree, pChild->pParent);
nodeReference(pNode);
pChild->pParent = pNode;
}
}
return xSetMapping(pRtree, iRowid, pNode->iNode);
}
static int SplitNode(
Rtree *pRtree,
RtreeNode *pNode,
RtreeCell *pCell,
| > | 197114 197115 197116 197117 197118 197119 197120 197121 197122 197123 197124 197125 197126 197127 197128 |
}
if( pChild ){
nodeRelease(pRtree, pChild->pParent);
nodeReference(pNode);
pChild->pParent = pNode;
}
}
if( NEVER(pNode==0) ) return SQLITE_ERROR;
return xSetMapping(pRtree, iRowid, pNode->iNode);
}
static int SplitNode(
Rtree *pRtree,
RtreeNode *pNode,
RtreeCell *pCell,
|
| ︙ | ︙ | |||
196874 196875 196876 196877 196878 196879 196880 196881 196882 196883 196884 196885 196886 196887 |
memset(&node, 0, sizeof(RtreeNode));
memset(&tree, 0, sizeof(Rtree));
tree.nDim = (u8)sqlite3_value_int(apArg[0]);
if( tree.nDim<1 || tree.nDim>5 ) return;
tree.nDim2 = tree.nDim*2;
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
nData = sqlite3_value_bytes(apArg[1]);
if( nData<4 ) return;
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
pOut = sqlite3_str_new(0);
for(ii=0; ii<NCELL(&node); ii++){
RtreeCell cell;
| > | 198419 198420 198421 198422 198423 198424 198425 198426 198427 198428 198429 198430 198431 198432 198433 |
memset(&node, 0, sizeof(RtreeNode));
memset(&tree, 0, sizeof(Rtree));
tree.nDim = (u8)sqlite3_value_int(apArg[0]);
if( tree.nDim<1 || tree.nDim>5 ) return;
tree.nDim2 = tree.nDim*2;
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlite3_value_blob(apArg[1]);
if( node.zData==0 ) return;
nData = sqlite3_value_bytes(apArg[1]);
if( nData<4 ) return;
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
pOut = sqlite3_str_new(0);
for(ii=0; ii<NCELL(&node); ii++){
RtreeCell cell;
|
| ︙ | ︙ | |||
197705 197706 197707 197708 197709 197710 197711 197712 197713 197714 197715 197716 197717 |
static GeoPoly *geopolyFuncParam(
sqlite3_context *pCtx, /* Context for error messages */
sqlite3_value *pVal, /* The value to decode */
int *pRc /* Write error here */
){
GeoPoly *p = 0;
int nByte;
if( sqlite3_value_type(pVal)==SQLITE_BLOB
&& (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
){
const unsigned char *a = sqlite3_value_blob(pVal);
int nVertex;
if( a==0 ){
| > | | 199251 199252 199253 199254 199255 199256 199257 199258 199259 199260 199261 199262 199263 199264 199265 199266 199267 199268 199269 199270 199271 199272 |
static GeoPoly *geopolyFuncParam(
sqlite3_context *pCtx, /* Context for error messages */
sqlite3_value *pVal, /* The value to decode */
int *pRc /* Write error here */
){
GeoPoly *p = 0;
int nByte;
testcase( pCtx==0 );
if( sqlite3_value_type(pVal)==SQLITE_BLOB
&& (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
){
const unsigned char *a = sqlite3_value_blob(pVal);
int nVertex;
if( a==0 ){
if( pCtx ) sqlite3_result_error_nomem(pCtx);
return 0;
}
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
if( (a[0]==0 || a[0]==1)
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
){
p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
|
| ︙ | ︙ | |||
198538 198539 198540 198541 198542 198543 198544 |
pSeg->y = pSeg->y0;
pSeg->pNext = pActive;
pActive = pSeg;
needSort = 1;
}else{
/* Remove a segment */
if( pActive==pThisEvent->pSeg ){
| | | | 200085 200086 200087 200088 200089 200090 200091 200092 200093 200094 200095 200096 200097 200098 200099 200100 200101 200102 200103 |
pSeg->y = pSeg->y0;
pSeg->pNext = pActive;
pActive = pSeg;
needSort = 1;
}else{
/* Remove a segment */
if( pActive==pThisEvent->pSeg ){
pActive = ALWAYS(pActive) ? pActive->pNext : 0;
}else{
for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
if( pSeg->pNext==pThisEvent->pSeg ){
pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0;
break;
}
}
}
}
pThisEvent = pThisEvent->pNext;
}
|
| ︙ | ︙ | |||
198786 198787 198788 198789 198790 198791 198792 198793 198794 198795 198796 198797 198798 198799 |
** with the configured constraints.
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && idxNum<=3 ){
RtreeCoord bbox[4];
RtreeConstraint *p;
assert( argc==1 );
geopolyBBox(0, argv[0], bbox, &rc);
if( rc ){
goto geopoly_filter_end;
}
pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4);
pCsr->nConstraint = 4;
if( p==0 ){
| > | 200333 200334 200335 200336 200337 200338 200339 200340 200341 200342 200343 200344 200345 200346 200347 |
** with the configured constraints.
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && idxNum<=3 ){
RtreeCoord bbox[4];
RtreeConstraint *p;
assert( argc==1 );
assert( argv[0]!=0 );
geopolyBBox(0, argv[0], bbox, &rc);
if( rc ){
goto geopoly_filter_end;
}
pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4);
pCsr->nConstraint = 4;
if( p==0 ){
|
| ︙ | ︙ | |||
199013 199014 199015 199016 199017 199018 199019 199020 199021 199022 199023 199024 199025 199026 |
cell.iRowid = newRowid;
if( nData>1 /* not a DELETE */
&& (!oldRowidValid /* INSERT */
|| !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|| oldRowid!=newRowid) /* Rowid change */
){
geopolyBBox(0, aData[2], cell.aCoord, &rc);
if( rc ){
if( rc==SQLITE_ERROR ){
pVtab->zErrMsg =
sqlite3_mprintf("_shape does not contain a valid polygon");
}
goto geopoly_update_end;
| > | 200561 200562 200563 200564 200565 200566 200567 200568 200569 200570 200571 200572 200573 200574 200575 |
cell.iRowid = newRowid;
if( nData>1 /* not a DELETE */
&& (!oldRowidValid /* INSERT */
|| !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|| oldRowid!=newRowid) /* Rowid change */
){
assert( aData[2]!=0 );
geopolyBBox(0, aData[2], cell.aCoord, &rc);
if( rc ){
if( rc==SQLITE_ERROR ){
pVtab->zErrMsg =
sqlite3_mprintf("_shape does not contain a valid polygon");
}
goto geopoly_update_end;
|
| ︙ | ︙ | |||
200939 200940 200941 200942 200943 200944 200945 200946 200947 200948 200949 200950 200951 200952 |
/*
** Swap two objects of type TYPE.
*/
#if !defined(SQLITE_AMALGAMATION)
# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
#endif
/*
** The rbu_state table is used to save the state of a partially applied
** update so that it can be resumed later. The table consists of integer
** keys mapped to values as follows:
**
** RBU_STATE_STAGE:
| > > > > > > > | 202488 202489 202490 202491 202492 202493 202494 202495 202496 202497 202498 202499 202500 202501 202502 202503 202504 202505 202506 202507 202508 |
/*
** Swap two objects of type TYPE.
*/
#if !defined(SQLITE_AMALGAMATION)
# define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
#endif
/*
** Name of the URI option that causes RBU to take an exclusive lock as
** part of the incremental checkpoint operation.
*/
#define RBU_EXCLUSIVE_CHECKPOINT "rbu_exclusive_checkpoint"
/*
** The rbu_state table is used to save the state of a partially applied
** update so that it can be resumed later. The table consists of integer
** keys mapped to values as follows:
**
** RBU_STATE_STAGE:
|
| ︙ | ︙ | |||
202386 202387 202388 202389 202390 202391 202392 | ** ** except that the "?" placeholders are replaced with literal values. ** ** If the expression cannot be created, NULL is returned. In this case, ** the caller has to use an OFFSET clause to extract only the required ** rows from the sourct table, just as it does for an RBU update operation. */ | | | 203942 203943 203944 203945 203946 203947 203948 203949 203950 203951 203952 203953 203954 203955 203956 |
**
** except that the "?" placeholders are replaced with literal values.
**
** If the expression cannot be created, NULL is returned. In this case,
** the caller has to use an OFFSET clause to extract only the required
** rows from the sourct table, just as it does for an RBU update operation.
*/
static char *rbuVacuumIndexStart(
sqlite3rbu *p, /* RBU handle */
RbuObjIter *pIter /* RBU iterator object */
){
char *zOrder = 0;
char *zLhs = 0;
char *zSelect = 0;
char *zVector = 0;
|
| ︙ | ︙ | |||
203586 203587 203588 203589 203590 203591 203592 203593 | return pRet; } /* ** Open the database handle and attach the RBU database as "rbu". If an ** error occurs, leave an error code and message in the RBU handle. */ | > > > > | > > | 205142 205143 205144 205145 205146 205147 205148 205149 205150 205151 205152 205153 205154 205155 205156 205157 205158 205159 205160 205161 205162 205163 205164 205165 205166 205167 205168 |
return pRet;
}
/*
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
**
** If argument dbMain is not NULL, then it is a database handle already
** open on the target database. Use this handle instead of opening a new
** one.
*/
static void rbuOpenDatabase(sqlite3rbu *p, sqlite3 *dbMain, int *pbRetry){
assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
assert( dbMain==0 || rbuIsVacuum(p)==0 );
/* Open the RBU database */
p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
p->dbMain = dbMain;
if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
if( p->zState==0 ){
const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
}
|
| ︙ | ︙ | |||
203958 203959 203960 203961 203962 203963 203964 | iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); } /* | | > | > | > | > | | | | > > > > > > > > > > > > | 205520 205521 205522 205523 205524 205525 205526 205527 205528 205529 205530 205531 205532 205533 205534 205535 205536 205537 205538 205539 205540 205541 205542 205543 205544 205545 205546 205547 205548 205549 205550 205551 205552 205553 205554 205555 205556 205557 205558 |
iOff = (i64)(pFrame->iDbPage-1) * p->pgsz;
p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff);
}
/*
** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if
** successful, or an SQLite error code otherwise.
*/
static int rbuLockDatabase(sqlite3 *db){
int rc = SQLITE_OK;
sqlite3_file *fd = 0;
sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd);
if( fd->pMethods ){
rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED);
if( rc==SQLITE_OK ){
rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE);
}
}
return rc;
}
/*
** Return true if the database handle passed as the only argument
** was opened with the rbu_exclusive_checkpoint=1 URI parameter
** specified. Or false otherwise.
*/
static int rbuExclusiveCheckpoint(sqlite3 *db){
const char *zUri = sqlite3_db_filename(db, 0);
return sqlite3_uri_boolean(zUri, RBU_EXCLUSIVE_CHECKPOINT, 0);
}
#if defined(_WIN32_WCE)
static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
int nChar;
LPWSTR zWideFilename;
|
| ︙ | ︙ | |||
204024 204025 204026 204027 204028 204029 204030 |
/* Move the *-oal file to *-wal. At this point connection p->db is
** holding a SHARED lock on the target database file (because it is
** in WAL mode). So no other connection may be writing the db.
**
** In order to ensure that there are no database readers, an EXCLUSIVE
** lock is obtained here before the *-oal is moved to *-wal.
*/
| | < | | | | | | | | > > > > > > > | 205602 205603 205604 205605 205606 205607 205608 205609 205610 205611 205612 205613 205614 205615 205616 205617 205618 205619 205620 205621 205622 205623 205624 205625 205626 205627 205628 205629 205630 205631 205632 205633 |
/* Move the *-oal file to *-wal. At this point connection p->db is
** holding a SHARED lock on the target database file (because it is
** in WAL mode). So no other connection may be writing the db.
**
** In order to ensure that there are no database readers, an EXCLUSIVE
** lock is obtained here before the *-oal is moved to *-wal.
*/
sqlite3 *dbMain = 0;
rbuFileSuffix3(zBase, zWal);
rbuFileSuffix3(zBase, zOal);
/* Re-open the databases. */
rbuObjIterFinalize(&p->objiter);
sqlite3_close(p->dbRbu);
sqlite3_close(p->dbMain);
p->dbMain = 0;
p->dbRbu = 0;
dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
if( dbMain ){
assert( p->rc==SQLITE_OK );
p->rc = rbuLockDatabase(dbMain);
}
if( p->rc==SQLITE_OK ){
#if defined(_WIN32_WCE)
{
LPWSTR zWideOal;
LPWSTR zWideWal;
zWideOal = rbuWinUtf8ToUnicode(zOal);
if( zWideOal ){
|
| ︙ | ︙ | |||
204062 204063 204064 204065 204066 204067 204068 |
}else{
p->rc = SQLITE_IOERR_NOMEM;
}
}
#else
p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
#endif
| | > > > > > > > > > | | | < | 205646 205647 205648 205649 205650 205651 205652 205653 205654 205655 205656 205657 205658 205659 205660 205661 205662 205663 205664 205665 205666 205667 205668 205669 205670 205671 205672 |
}else{
p->rc = SQLITE_IOERR_NOMEM;
}
}
#else
p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
#endif
}
if( p->rc!=SQLITE_OK
|| rbuIsVacuum(p)
|| rbuExclusiveCheckpoint(dbMain)==0
){
sqlite3_close(dbMain);
dbMain = 0;
}
if( p->rc==SQLITE_OK ){
rbuOpenDatabase(p, dbMain, 0);
rbuSetupCheckpoint(p, 0);
}
}
sqlite3_free(zWal);
sqlite3_free(zOal);
}
|
| ︙ | ︙ | |||
204817 204818 204819 204820 204821 204822 204823 |
/* If the first attempt to open the database file fails and the bRetry
** flag it set, this means that the db was not opened because it seemed
** to be a wal-mode db. But, this may have happened due to an earlier
** RBU vacuum operation leaving an old wal file in the directory.
** If this is the case, it will have been checkpointed and deleted
** when the handle was closed and a second attempt to open the
** database may succeed. */
| | | | 206409 206410 206411 206412 206413 206414 206415 206416 206417 206418 206419 206420 206421 206422 206423 206424 206425 |
/* If the first attempt to open the database file fails and the bRetry
** flag it set, this means that the db was not opened because it seemed
** to be a wal-mode db. But, this may have happened due to an earlier
** RBU vacuum operation leaving an old wal file in the directory.
** If this is the case, it will have been checkpointed and deleted
** when the handle was closed and a second attempt to open the
** database may succeed. */
rbuOpenDatabase(p, 0, &bRetry);
if( bRetry ){
rbuOpenDatabase(p, 0, 0);
}
}
if( p->rc==SQLITE_OK ){
pState = rbuLoadState(p);
assert( pState || p->rc!=SQLITE_OK );
if( p->rc==SQLITE_OK ){
|
| ︙ | ︙ | |||
204914 204915 204916 204917 204918 204919 204920 204921 204922 204923 204924 204925 204926 204927 |
if( p->rc==SQLITE_OK ){
rbuSetupOal(p, pState);
}
}
}else if( p->eStage==RBU_STAGE_MOVE ){
/* no-op */
}else if( p->eStage==RBU_STAGE_CKPT ){
rbuSetupCheckpoint(p, pState);
}else if( p->eStage==RBU_STAGE_DONE ){
p->rc = SQLITE_DONE;
}else{
p->rc = SQLITE_CORRUPT;
}
}
| > > > > > > > > | 206506 206507 206508 206509 206510 206511 206512 206513 206514 206515 206516 206517 206518 206519 206520 206521 206522 206523 206524 206525 206526 206527 |
if( p->rc==SQLITE_OK ){
rbuSetupOal(p, pState);
}
}
}else if( p->eStage==RBU_STAGE_MOVE ){
/* no-op */
}else if( p->eStage==RBU_STAGE_CKPT ){
if( !rbuIsVacuum(p) && rbuExclusiveCheckpoint(p->dbMain) ){
/* If the rbu_exclusive_checkpoint=1 URI parameter was specified
** and an incremental checkpoint is being resumed, attempt an
** exclusive lock on the db file. If this fails, so be it. */
p->eStage = RBU_STAGE_DONE;
rbuLockDatabase(p->dbMain);
p->eStage = RBU_STAGE_CKPT;
}
rbuSetupCheckpoint(p, pState);
}else if( p->eStage==RBU_STAGE_DONE ){
p->rc = SQLITE_DONE;
}else{
p->rc = SQLITE_CORRUPT;
}
}
|
| ︙ | ︙ | |||
204951 204952 204953 204954 204955 204956 204957 |
*/
SQLITE_API sqlite3rbu *sqlite3rbu_open(
const char *zTarget,
const char *zRbu,
const char *zState
){
if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
| < | 206551 206552 206553 206554 206555 206556 206557 206558 206559 206560 206561 206562 206563 206564 |
*/
SQLITE_API sqlite3rbu *sqlite3rbu_open(
const char *zTarget,
const char *zRbu,
const char *zState
){
if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
return openRbuHandle(zTarget, zRbu, zState);
}
/*
** Open a handle to begin or resume an RBU VACUUM operation.
*/
SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
|
| ︙ | ︙ | |||
207871 207872 207873 207874 207875 207876 207877 |
}
n = sqlite3_value_bytes(pValue);
if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
nVarint = sessionVarintLen(n);
if( aBuf ){
sessionVarintPut(&aBuf[1], n);
| | | 209470 209471 209472 209473 209474 209475 209476 209477 209478 209479 209480 209481 209482 209483 209484 |
}
n = sqlite3_value_bytes(pValue);
if( z==0 && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM;
nVarint = sessionVarintLen(n);
if( aBuf ){
sessionVarintPut(&aBuf[1], n);
if( n>0 ) memcpy(&aBuf[nVarint + 1], z, n);
}
nByte = 1 + nVarint + n;
break;
}
}
}else{
|
| ︙ | ︙ | |||
208476 208477 208478 208479 208480 208481 208482 208483 208484 208485 208486 208487 |
"SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
"SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
"SELECT 2, 'stat', '', 0, '', 0"
);
}else if( rc==SQLITE_ERROR ){
zPragma = sqlite3_mprintf("");
}else{
return rc;
}
}else{
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
}
| > > > > | > > > > > > | > > > > > > | 210075 210076 210077 210078 210079 210080 210081 210082 210083 210084 210085 210086 210087 210088 210089 210090 210091 210092 210093 210094 210095 210096 210097 210098 210099 210100 210101 210102 210103 210104 210105 210106 210107 210108 210109 210110 210111 210112 210113 210114 |
"SELECT 0, 'tbl', '', 0, '', 1 UNION ALL "
"SELECT 1, 'idx', '', 0, '', 2 UNION ALL "
"SELECT 2, 'stat', '', 0, '', 0"
);
}else if( rc==SQLITE_ERROR ){
zPragma = sqlite3_mprintf("");
}else{
*pazCol = 0;
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
return rc;
}
}else{
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
}
if( !zPragma ){
*pazCol = 0;
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
return SQLITE_NOMEM;
}
rc = sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
sqlite3_free(zPragma);
if( rc!=SQLITE_OK ){
*pazCol = 0;
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
return rc;
}
nByte = nThis + 1;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
nByte += sqlite3_column_bytes(pStmt, 1);
nDbCol++;
}
rc = sqlite3_reset(pStmt);
|
| ︙ | ︙ | |||
208903 208904 208905 208906 208907 208908 208909 |
/* If there is a table-filter configured, invoke it. If it returns 0,
** do not automatically add the new table. */
if( pSession->xTableFilter==0
|| pSession->xTableFilter(pSession->pFilterCtx, zName)
){
rc = sqlite3session_attach(pSession, zName);
if( rc==SQLITE_OK ){
| | > > > > | 210518 210519 210520 210521 210522 210523 210524 210525 210526 210527 210528 210529 210530 210531 210532 210533 210534 210535 210536 |
/* If there is a table-filter configured, invoke it. If it returns 0,
** do not automatically add the new table. */
if( pSession->xTableFilter==0
|| pSession->xTableFilter(pSession->pFilterCtx, zName)
){
rc = sqlite3session_attach(pSession, zName);
if( rc==SQLITE_OK ){
pRet = pSession->pTable;
while( ALWAYS(pRet) && pRet->pNext ){
pRet = pRet->pNext;
}
assert( pRet!=0 );
assert( 0==sqlite3_strnicmp(pRet->zName, zName, nName+1) );
}
}
}
assert( rc==SQLITE_OK || pRet==0 );
*ppTab = pRet;
|
| ︙ | ︙ | |||
209676 209677 209678 209679 209680 209681 209682 209683 209684 209685 209686 209687 209688 209689 |
int rc = SQLITE_OK;
SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */
int bNoop = 1; /* Set to zero if any values are modified */
int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */
int i; /* Used to iterate through columns */
u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */
sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
sessionAppendByte(pBuf, p->bIndirect, &rc);
for(i=0; i<sqlite3_column_count(pStmt); i++){
int bChanged = 0;
int nAdvance;
int eType = *pCsr;
switch( eType ){
| > | 211295 211296 211297 211298 211299 211300 211301 211302 211303 211304 211305 211306 211307 211308 211309 |
int rc = SQLITE_OK;
SessionBuffer buf2 = {0,0,0}; /* Buffer to accumulate new.* record in */
int bNoop = 1; /* Set to zero if any values are modified */
int nRewind = pBuf->nBuf; /* Set to zero if any values are modified */
int i; /* Used to iterate through columns */
u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */
assert( abPK!=0 );
sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
sessionAppendByte(pBuf, p->bIndirect, &rc);
for(i=0; i<sqlite3_column_count(pStmt); i++){
int bChanged = 0;
int nAdvance;
int eType = *pCsr;
switch( eType ){
|
| ︙ | ︙ | |||
209980 209981 209982 209983 209984 209985 209986 |
void **ppChangeset /* OUT: Buffer containing changeset */
){
sqlite3 *db = pSession->db; /* Source database handle */
SessionTable *pTab; /* Used to iterate through attached tables */
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
int rc; /* Return code */
| | > > | | | 211600 211601 211602 211603 211604 211605 211606 211607 211608 211609 211610 211611 211612 211613 211614 211615 211616 211617 211618 211619 211620 211621 211622 211623 211624 211625 211626 211627 211628 211629 211630 211631 211632 211633 211634 211635 211636 |
void **ppChangeset /* OUT: Buffer containing changeset */
){
sqlite3 *db = pSession->db; /* Source database handle */
SessionTable *pTab; /* Used to iterate through attached tables */
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
int rc; /* Return code */
assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
/* Zero the output variables in case an error occurs. If this session
** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
** this call will be a no-op. */
if( xOutput==0 ){
assert( pnChangeset!=0 && ppChangeset!=0 );
*pnChangeset = 0;
*ppChangeset = 0;
}
if( pSession->rc ) return pSession->rc;
rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_mutex_enter(sqlite3_db_mutex(db));
for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
if( pTab->nEntry ){
const char *zName = pTab->zName;
int nCol = 0; /* Number of columns in table */
u8 *abPK = 0; /* Primary key array */
const char **azCol = 0; /* Table columns */
int i; /* Used to iterate through hash buckets */
sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */
int nRewind = buf.nBuf; /* Initial size of write buffer */
int nNoop; /* Size of buffer after writing tbl header */
/* Check the table schema is still Ok. */
|
| ︙ | ︙ | |||
210038 210039 210040 210041 210042 210043 210044 210045 210046 210047 210048 210049 210050 210051 |
int iCol;
sessionAppendByte(&buf, SQLITE_INSERT, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc);
for(iCol=0; iCol<nCol; iCol++){
sessionAppendCol(&buf, pSel, iCol, &rc);
}
}else{
rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
}
}else if( p->op!=SQLITE_INSERT ){
rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK);
}
if( rc==SQLITE_OK ){
rc = sqlite3_reset(pSel);
| > | 211660 211661 211662 211663 211664 211665 211666 211667 211668 211669 211670 211671 211672 211673 211674 |
int iCol;
sessionAppendByte(&buf, SQLITE_INSERT, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc);
for(iCol=0; iCol<nCol; iCol++){
sessionAppendCol(&buf, pSel, iCol, &rc);
}
}else{
assert( abPK!=0 ); /* Because sessionSelectStmt() returned ok */
rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
}
}else if( p->op!=SQLITE_INSERT ){
rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK);
}
if( rc==SQLITE_OK ){
rc = sqlite3_reset(pSel);
|
| ︙ | ︙ | |||
210098 210099 210100 210101 210102 210103 210104 |
** using sqlite3_free().
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
){
| > > > | > > > | 211721 211722 211723 211724 211725 211726 211727 211728 211729 211730 211731 211732 211733 211734 211735 211736 211737 211738 211739 211740 211741 211742 211743 211744 211745 211746 211747 211748 211749 211750 211751 211752 211753 211754 211755 211756 211757 211758 211759 211760 211761 211762 211763 211764 211765 211766 211767 211768 211769 211770 211771 211772 211773 211774 211775 211776 211777 211778 211779 211780 211781 |
** using sqlite3_free().
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
){
int rc;
if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE;
rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
assert( rc || pnChangeset==0
|| pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
);
return rc;
}
/*
** Streaming version of sqlite3session_changeset().
*/
SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
){
if( xOutput==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0);
}
/*
** Streaming version of sqlite3session_patchset().
*/
SQLITE_API int sqlite3session_patchset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
){
if( xOutput==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0);
}
/*
** Obtain a patchset object containing all changes recorded by the
** session object passed as the first argument.
**
** It is the responsibility of the caller to eventually free the buffer
** using sqlite3_free().
*/
SQLITE_API int sqlite3session_patchset(
sqlite3_session *pSession, /* Session object */
int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
void **ppPatchset /* OUT: Buffer containing changeset */
){
if( pnPatchset==0 || ppPatchset==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset);
}
/*
** Enable or disable the session object passed as the first argument.
*/
SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable){
|
| ︙ | ︙ | |||
211102 211103 211104 211105 211106 211107 211108 |
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
if( rc!=SQLITE_OK ) goto finished_invert;
}
}
assert( rc==SQLITE_OK );
| | | | 212731 212732 212733 212734 212735 212736 212737 212738 212739 212740 212741 212742 212743 212744 212745 212746 212747 212748 212749 |
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
if( rc!=SQLITE_OK ) goto finished_invert;
}
}
assert( rc==SQLITE_OK );
if( pnInverted && ALWAYS(ppInverted) ){
*pnInverted = sOut.nBuf;
*ppInverted = sOut.aBuf;
sOut.aBuf = 0;
}else if( sOut.nBuf>0 && ALWAYS(xOutput!=0) ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
}
finished_invert:
sqlite3_free(sOut.aBuf);
sqlite3_free(apVal);
sqlite3_free(sPK.aBuf);
|
| ︙ | ︙ | |||
211562 211563 211564 211565 211566 211567 211568 |
** argument iterator points to a suitable entry. Make sure that xValue
** is one of these to guarantee that it is safe to ignore the return
** in the code below. */
assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new );
for(i=0; rc==SQLITE_OK && i<nCol; i++){
if( !abPK || abPK[i] ){
| | | 213191 213192 213193 213194 213195 213196 213197 213198 213199 213200 213201 213202 213203 213204 213205 |
** argument iterator points to a suitable entry. Make sure that xValue
** is one of these to guarantee that it is safe to ignore the return
** in the code below. */
assert( xValue==sqlite3changeset_old || xValue==sqlite3changeset_new );
for(i=0; rc==SQLITE_OK && i<nCol; i++){
if( !abPK || abPK[i] ){
sqlite3_value *pVal = 0;
(void)xValue(pIter, i, &pVal);
if( pVal==0 ){
/* The value in the changeset was "undefined". This indicates a
** corrupt changeset blob. */
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = sessionBindValue(pStmt, i+1, pVal);
|
| ︙ | ︙ | |||
212705 212706 212707 212708 212709 212710 212711 |
}
}
}
if( rc==SQLITE_OK ){
if( xOutput ){
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
| | | | 214334 214335 214336 214337 214338 214339 214340 214341 214342 214343 214344 214345 214346 214347 214348 214349 214350 |
}
}
}
if( rc==SQLITE_OK ){
if( xOutput ){
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
}else if( ppOut ){
*ppOut = buf.aBuf;
if( pnOut ) *pnOut = buf.nBuf;
buf.aBuf = 0;
}
}
sqlite3_free(buf.aBuf);
return rc;
}
|
| ︙ | ︙ | |||
213107 213108 213109 213110 213111 213112 213113 |
}
if( rc==SQLITE_OK ){
if( xOutput ){
if( sOut.nBuf>0 ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
}
| | | 214736 214737 214738 214739 214740 214741 214742 214743 214744 214745 214746 214747 214748 214749 214750 |
}
if( rc==SQLITE_OK ){
if( xOutput ){
if( sOut.nBuf>0 ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
}
}else if( ppOut ){
*ppOut = (void*)sOut.aBuf;
*pnOut = sOut.nBuf;
sOut.aBuf = 0;
}
}
sqlite3_free(sOut.aBuf);
return rc;
|
| ︙ | ︙ | |||
213850 213851 213852 213853 213854 213855 213856 | typedef sqlite3_uint64 u64; #ifndef ArraySize # define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) #endif #define testcase(x) | > > > > > | | > > > > > > > | 215479 215480 215481 215482 215483 215484 215485 215486 215487 215488 215489 215490 215491 215492 215493 215494 215495 215496 215497 215498 215499 215500 215501 215502 215503 215504 215505 215506 | typedef sqlite3_uint64 u64; #ifndef ArraySize # define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) #endif #define testcase(x) #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) # define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 #endif #if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) # define ALWAYS(X) (1) # define NEVER(X) (0) #elif !defined(NDEBUG) # define ALWAYS(X) ((X)?1:(assert(0),0)) # define NEVER(X) ((X)?(assert(0),1):0) #else # define ALWAYS(X) (X) # define NEVER(X) (X) #endif #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) /* ** Constants for the largest and smallest possible 64-bit signed integers. */ |
| ︙ | ︙ | |||
213911 213912 213913 213914 213915 213916 213917 | # define assert_nc(x) assert(x) #endif /* ** A version of memcmp() that does not cause asan errors if one of the pointer ** parameters is NULL and the number of bytes to compare is zero. */ | | | 215552 215553 215554 215555 215556 215557 215558 215559 215560 215561 215562 215563 215564 215565 215566 | # define assert_nc(x) assert(x) #endif /* ** A version of memcmp() that does not cause asan errors if one of the pointer ** parameters is NULL and the number of bytes to compare is zero. */ #define fts5Memcmp(s1, s2, n) ((n)<=0 ? 0 : memcmp((s1), (s2), (n))) /* Mark a function parameter as unused, to suppress nuisance compiler ** warnings. */ #ifndef UNUSED_PARAM # define UNUSED_PARAM(X) (void)(X) #endif |
| ︙ | ︙ | |||
215030 215031 215032 215033 215034 215035 215036 215037 215038 | #else fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ #endif }; typedef struct fts5yyParser fts5yyParser; #ifndef NDEBUG /* #include <stdio.h> */ | > < | 216671 216672 216673 216674 216675 216676 216677 216678 216679 216680 216681 216682 216683 216684 216685 216686 216687 | #else fts5yyStackEntry fts5yystack[fts5YYSTACKDEPTH]; /* The parser's stack */ fts5yyStackEntry *fts5yystackEnd; /* Last entry in the stack */ #endif }; typedef struct fts5yyParser fts5yyParser; /* #include <assert.h> */ #ifndef NDEBUG /* #include <stdio.h> */ static FILE *fts5yyTraceFILE = 0; static char *fts5yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG /* ** Turn parser tracing on by giving a stream to which to write the trace |
| ︙ | ︙ | |||
215969 215970 215971 215972 215973 215974 215975 |
while(1){ /* Exit by "break" */
assert( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystack );
assert( fts5yyact==fts5yypParser->fts5yytos->stateno );
fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact);
if( fts5yyact >= fts5YY_MIN_REDUCE ){
unsigned int fts5yyruleno = fts5yyact - fts5YY_MIN_REDUCE; /* Reduce by this rule */
| < > | 217610 217611 217612 217613 217614 217615 217616 217617 217618 217619 217620 217621 217622 217623 217624 217625 |
while(1){ /* Exit by "break" */
assert( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystack );
assert( fts5yyact==fts5yypParser->fts5yytos->stateno );
fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact);
if( fts5yyact >= fts5YY_MIN_REDUCE ){
unsigned int fts5yyruleno = fts5yyact - fts5YY_MIN_REDUCE; /* Reduce by this rule */
#ifndef NDEBUG
assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
if( fts5yyTraceFILE ){
int fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
if( fts5yysize ){
fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
fts5yyTracePrompt,
fts5yyruleno, fts5yyRuleName[fts5yyruleno],
fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
|
| ︙ | ︙ | |||
216937 216938 216939 216940 216941 216942 216943 |
*/
static void sqlite3Fts5BufferAppendBlob(
int *pRc,
Fts5Buffer *pBuf,
u32 nData,
const u8 *pData
){
| < | 218578 218579 218580 218581 218582 218583 218584 218585 218586 218587 218588 218589 218590 218591 |
*/
static void sqlite3Fts5BufferAppendBlob(
int *pRc,
Fts5Buffer *pBuf,
u32 nData,
const u8 *pData
){
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
pBuf->n += nData;
}
}
|
| ︙ | ︙ | |||
217049 217050 217051 217052 217053 217054 217055 |
/* EOF */
*piOff = -1;
return 1;
}else{
i64 iOff = *piOff;
u32 iVal;
fts5FastGetVarint32(a, i, iVal);
| < | 218689 218690 218691 218692 218693 218694 218695 218696 218697 218698 218699 218700 218701 218702 |
/* EOF */
*piOff = -1;
return 1;
}else{
i64 iOff = *piOff;
u32 iVal;
fts5FastGetVarint32(a, i, iVal);
if( iVal<=1 ){
if( iVal==0 ){
*pi = i;
return 0;
}
fts5FastGetVarint32(a, i, iVal);
iOff = ((i64)iVal) << 32;
|
| ︙ | ︙ | |||
217844 217845 217846 217847 217848 217849 217850 217851 217852 217853 217854 217855 217856 217857 217858 217859 217860 217861 217862 217863 217864 217865 217866 |
int bOption = 0;
int bMustBeCol = 0;
z = fts5ConfigGobbleWord(&rc, zOrig, &zOne, &bMustBeCol);
z = fts5ConfigSkipWhitespace(z);
if( z && *z=='=' ){
bOption = 1;
z++;
if( bMustBeCol ) z = 0;
}
z = fts5ConfigSkipWhitespace(z);
if( z && z[0] ){
int bDummy;
z = fts5ConfigGobbleWord(&rc, z, &zTwo, &bDummy);
if( z && z[0] ) z = 0;
}
if( rc==SQLITE_OK ){
if( z==0 ){
*pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
rc = SQLITE_ERROR;
}else{
if( bOption ){
| > | > > > > | 219483 219484 219485 219486 219487 219488 219489 219490 219491 219492 219493 219494 219495 219496 219497 219498 219499 219500 219501 219502 219503 219504 219505 219506 219507 219508 219509 219510 219511 219512 219513 219514 219515 219516 219517 219518 |
int bOption = 0;
int bMustBeCol = 0;
z = fts5ConfigGobbleWord(&rc, zOrig, &zOne, &bMustBeCol);
z = fts5ConfigSkipWhitespace(z);
if( z && *z=='=' ){
bOption = 1;
assert( zOne!=0 );
z++;
if( bMustBeCol ) z = 0;
}
z = fts5ConfigSkipWhitespace(z);
if( z && z[0] ){
int bDummy;
z = fts5ConfigGobbleWord(&rc, z, &zTwo, &bDummy);
if( z && z[0] ) z = 0;
}
if( rc==SQLITE_OK ){
if( z==0 ){
*pzErr = sqlite3_mprintf("parse error in \"%s\"", zOrig);
rc = SQLITE_ERROR;
}else{
if( bOption ){
rc = fts5ConfigParseSpecial(pGlobal, pRet,
ALWAYS(zOne)?zOne:"",
zTwo?zTwo:"",
pzErr
);
}else{
rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
zOne = 0;
}
}
}
|
| ︙ | ︙ | |||
218677 218678 218679 218680 218681 218682 218683 218684 218685 218686 218687 218688 218689 218690 |
** that it points to.
*/
static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
i64 iRet = 0;
int bRetValid = 0;
Fts5ExprTerm *p;
assert( pTerm->pSynonym );
assert( bDesc==0 || bDesc==1 );
for(p=pTerm; p; p=p->pSynonym){
if( 0==sqlite3Fts5IterEof(p->pIter) ){
i64 iRowid = p->pIter->iRowid;
if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){
iRet = iRowid;
| > | 220321 220322 220323 220324 220325 220326 220327 220328 220329 220330 220331 220332 220333 220334 220335 |
** that it points to.
*/
static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
i64 iRet = 0;
int bRetValid = 0;
Fts5ExprTerm *p;
assert( pTerm );
assert( pTerm->pSynonym );
assert( bDesc==0 || bDesc==1 );
for(p=pTerm; p; p=p->pSynonym){
if( 0==sqlite3Fts5IterEof(p->pIter) ){
i64 iRowid = p->pIter->iRowid;
if( bRetValid==0 || (bDesc!=(iRowid<iRet)) ){
iRet = iRowid;
|
| ︙ | ︙ | |||
220117 220118 220119 220120 220121 220122 220123 |
}
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
| | | 221762 221763 221764 221765 221766 221767 221768 221769 221770 221771 221772 221773 221774 221775 221776 |
}
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
/* All the allocations succeeded. Put the expression object together. */
pNew->pIndex = pExpr->pIndex;
pNew->pConfig = pExpr->pConfig;
pNew->nPhrase = 1;
pNew->apExprPhrase[0] = sCtx.pPhrase;
pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
pNew->pRoot->pNear->nPhrase = 1;
|
| ︙ | ︙ | |||
221098 221099 221100 221101 221102 221103 221104 221105 221106 221107 221108 221109 221110 221111 221112 221113 |
struct Fts5PoslistPopulator {
Fts5PoslistWriter writer;
int bOk; /* True if ok to populate */
int bMiss;
};
static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
if( pRet ){
int i;
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
for(i=0; i<pExpr->nPhrase; i++){
Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
| > > > > > > > > > | | 222743 222744 222745 222746 222747 222748 222749 222750 222751 222752 222753 222754 222755 222756 222757 222758 222759 222760 222761 222762 222763 222764 222765 222766 222767 222768 222769 222770 222771 222772 222773 222774 222775 |
struct Fts5PoslistPopulator {
Fts5PoslistWriter writer;
int bOk; /* True if ok to populate */
int bMiss;
};
/*
** Clear the position lists associated with all phrases in the expression
** passed as the first argument. Argument bLive is true if the expression
** might be pointing to a real entry, otherwise it has just been reset.
**
** At present this function is only used for detail=col and detail=none
** fts5 tables. This implies that all phrases must be at most 1 token
** in size, as phrase matches are not supported without detail=full.
*/
static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
if( pRet ){
int i;
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
for(i=0; i<pExpr->nPhrase; i++){
Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
assert( pExpr->apExprPhrase[i]->nTerm<=1 );
if( bLive &&
(pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
){
pRet[i].bMiss = 1;
}else{
pBuf->n = 0;
}
|
| ︙ | ︙ | |||
221658 221659 221660 221661 221662 221663 221664 |
}
if( iCol>=0 ){
if( pHash->eDetail==FTS5_DETAIL_NONE ){
p->bContent = 1;
}else{
/* Append a new column value, if necessary */
| | | 223312 223313 223314 223315 223316 223317 223318 223319 223320 223321 223322 223323 223324 223325 223326 |
}
if( iCol>=0 ){
if( pHash->eDetail==FTS5_DETAIL_NONE ){
p->bContent = 1;
}else{
/* Append a new column value, if necessary */
assert_nc( iCol>=p->iCol );
if( iCol!=p->iCol ){
if( pHash->eDetail==FTS5_DETAIL_FULL ){
pPtr[p->nData++] = 0x01;
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
p->iCol = (i16)iCol;
p->iPos = 0;
}else{
|
| ︙ | ︙ | |||
222463 222464 222465 222466 222467 222468 222469 |
**
** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
** +ve if pRight is smaller than pLeft. In other words:
**
** res = *pLeft - *pRight
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
| > | > > | | 224117 224118 224119 224120 224121 224122 224123 224124 224125 224126 224127 224128 224129 224130 224131 224132 224133 224134 224135 |
**
** Return -ve if pLeft is smaller than pRight, 0 if they are equal or
** +ve if pRight is smaller than pLeft. In other words:
**
** res = *pLeft - *pRight
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
int nCmp, res;
nCmp = MIN(pLeft->n, pRight->n);
assert( nCmp<=0 || pLeft->p!=0 );
assert( nCmp<=0 || pRight->p!=0 );
res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
return (res==0 ? (pLeft->n - pRight->n) : res);
}
static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
int ret;
fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret);
return ret;
|
| ︙ | ︙ | |||
222710 222711 222712 222713 222714 222715 222716 |
**
** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
** an error occurs, (*pRc) is set to an SQLite error code before returning.
*/
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
Fts5Structure *p = *pp;
if( *pRc==SQLITE_OK && p->nRef>1 ){
| | | 224367 224368 224369 224370 224371 224372 224373 224374 224375 224376 224377 224378 224379 224380 224381 |
**
** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
** an error occurs, (*pRc) is set to an SQLite error code before returning.
*/
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
Fts5Structure *p = *pp;
if( *pRc==SQLITE_OK && p->nRef>1 ){
i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
Fts5Structure *pNew;
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
if( pNew ){
int i;
memcpy(pNew, p, nByte);
for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0;
for(i=0; i<p->nLevel; i++){
|
| ︙ | ︙ | |||
223636 223637 223638 223639 223640 223641 223642 223643 223644 223645 223646 223647 223648 223649 |
pIter->pSeg = pSeg;
pIter->iLeafPgno = pSeg->pgnoFirst-1;
fts5SegIterNextPage(p, pIter);
}
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
assert_nc( pIter->pLeaf->nn>4 );
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
}
}
| > | 225293 225294 225295 225296 225297 225298 225299 225300 225301 225302 225303 225304 225305 225306 225307 |
pIter->pSeg = pSeg;
pIter->iLeafPgno = pSeg->pgnoFirst-1;
fts5SegIterNextPage(p, pIter);
}
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
assert( pIter->pLeaf!=0 );
assert_nc( pIter->pLeaf->nn>4 );
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
}
}
|
| ︙ | ︙ | |||
223738 223739 223740 223741 223742 223743 223744 |
pIter->pLeaf = pNew;
pIter->iLeafOffset = pIter->iTermLeafOffset;
}
}else{
int iRowidOff;
iRowidOff = fts5LeafFirstRowidOff(pNew);
if( iRowidOff ){
| > > > | | > | 225396 225397 225398 225399 225400 225401 225402 225403 225404 225405 225406 225407 225408 225409 225410 225411 225412 225413 225414 225415 |
pIter->pLeaf = pNew;
pIter->iLeafOffset = pIter->iTermLeafOffset;
}
}else{
int iRowidOff;
iRowidOff = fts5LeafFirstRowidOff(pNew);
if( iRowidOff ){
if( iRowidOff>=pNew->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
pIter->pLeaf = pNew;
pIter->iLeafOffset = iRowidOff;
}
}
}
if( pIter->pLeaf ){
u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset];
pIter->iLeafOffset += fts5GetVarint(a, (u64*)&pIter->iRowid);
break;
|
| ︙ | ︙ | |||
224140 224141 224142 224143 224144 224145 224146 |
*/
static void fts5LeafSeek(
Fts5Index *p, /* Leave any error code here */
int bGe, /* True for a >= search */
Fts5SegIter *pIter, /* Iterator to seek */
const u8 *pTerm, int nTerm /* Term to search for */
){
| | < | | | | 225802 225803 225804 225805 225806 225807 225808 225809 225810 225811 225812 225813 225814 225815 225816 225817 225818 225819 225820 225821 225822 225823 225824 225825 225826 225827 225828 225829 |
*/
static void fts5LeafSeek(
Fts5Index *p, /* Leave any error code here */
int bGe, /* True for a >= search */
Fts5SegIter *pIter, /* Iterator to seek */
const u8 *pTerm, int nTerm /* Term to search for */
){
u32 iOff;
const u8 *a = pIter->pLeaf->p;
u32 n = (u32)pIter->pLeaf->nn;
u32 nMatch = 0;
u32 nKeep = 0;
u32 nNew = 0;
u32 iTermOff;
u32 iPgidx; /* Current offset in pgidx */
int bEndOfPage = 0;
assert( p->rc==SQLITE_OK );
iPgidx = (u32)pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
iOff = iTermOff;
if( iOff>n ){
p->rc = FTS5_CORRUPT;
return;
}
|
| ︙ | ︙ | |||
224220 224221 224222 224223 224224 224225 224226 |
return;
}else if( bEndOfPage ){
do {
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf==0 ) return;
a = pIter->pLeaf->p;
if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
| | | | | 225881 225882 225883 225884 225885 225886 225887 225888 225889 225890 225891 225892 225893 225894 225895 225896 225897 225898 225899 225900 225901 225902 225903 |
return;
}else if( bEndOfPage ){
do {
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf==0 ) return;
a = pIter->pLeaf->p;
if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
iPgidx = (u32)pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
return;
}else{
nKeep = 0;
iTermOff = iOff;
n = (u32)pIter->pLeaf->nn;
iOff += fts5GetVarint32(&a[iOff], nNew);
break;
}
}
}while( 1 );
}
|
| ︙ | ︙ | |||
224596 224597 224598 224599 224600 224601 224602 |
}else{
fts5DataRelease(pIter->pNextLeaf);
pIter->pNextLeaf = 0;
pIter->iLeafPgno = iLeafPgno-1;
fts5SegIterNextPage(p, pIter);
assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );
| | | 226257 226258 226259 226260 226261 226262 226263 226264 226265 226266 226267 226268 226269 226270 226271 |
}else{
fts5DataRelease(pIter->pNextLeaf);
pIter->pNextLeaf = 0;
pIter->iLeafPgno = iLeafPgno-1;
fts5SegIterNextPage(p, pIter);
assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );
if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){
int iOff;
u8 *a = pIter->pLeaf->p;
int n = pIter->pLeaf->szLeaf;
iOff = fts5LeafFirstRowidOff(pIter->pLeaf);
if( iOff<4 || iOff>=n ){
p->rc = FTS5_CORRUPT;
|
| ︙ | ︙ | |||
225028 225029 225030 225031 225032 225033 225034 225035 225036 225037 225038 225039 225040 225041 225042 |
*/
static void fts5SegiterPoslist(
Fts5Index *p,
Fts5SegIter *pSeg,
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
}else{
if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
PoslistCallbackCtx sCtx;
sCtx.pBuf = pBuf;
| > > > > | 226689 226690 226691 226692 226693 226694 226695 226696 226697 226698 226699 226700 226701 226702 226703 226704 226705 226706 226707 |
*/
static void fts5SegiterPoslist(
Fts5Index *p,
Fts5SegIter *pSeg,
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
assert( pBuf!=0 );
assert( pSeg!=0 );
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
assert( pBuf->p!=0 );
assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING );
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
}else{
if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
PoslistCallbackCtx sCtx;
sCtx.pBuf = pBuf;
|
| ︙ | ︙ | |||
225252 225253 225254 225255 225256 225257 225258 225259 225260 225261 225262 225263 225264 225265 |
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}
static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
if( *pRc==SQLITE_OK ){
Fts5Config *pConfig = pIter->pIndex->pConfig;
if( pConfig->eDetail==FTS5_DETAIL_NONE ){
pIter->xSetOutputs = fts5IterSetOutputs_None;
}
else if( pIter->pColset==0 ){
| > | 226917 226918 226919 226920 226921 226922 226923 226924 226925 226926 226927 226928 226929 226930 226931 |
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
pIter->base.pData = pIter->poslist.p;
pIter->base.nData = pIter->poslist.n;
}
}
static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
assert( pIter!=0 || (*pRc)!=SQLITE_OK );
if( *pRc==SQLITE_OK ){
Fts5Config *pConfig = pIter->pIndex->pConfig;
if( pConfig->eDetail==FTS5_DETAIL_NONE ){
pIter->xSetOutputs = fts5IterSetOutputs_None;
}
else if( pIter->pColset==0 ){
|
| ︙ | ︙ | |||
225323 225324 225325 225326 225327 225328 225329 |
nSeg = pStruct->nSegment;
nSeg += (p->pHash ? 1 : 0);
}else{
nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
}
}
*ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
| | > > > | 226989 226990 226991 226992 226993 226994 226995 226996 226997 226998 226999 227000 227001 227002 227003 227004 227005 227006 |
nSeg = pStruct->nSegment;
nSeg += (p->pHash ? 1 : 0);
}else{
nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment);
}
}
*ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
if( pNew==0 ){
assert( p->rc!=SQLITE_OK );
goto fts5MultiIterNew_post_check;
}
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
pNew->pColset = pColset;
if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
fts5IterSetOutputCb(&p->rc, pNew);
}
|
| ︙ | ︙ | |||
225387 225388 225389 225390 225391 225392 225393 225394 225395 225396 225397 225398 225399 225400 |
pNew->xSetOutputs(pNew, pSeg);
}
}else{
fts5MultiIterFree(pNew);
*ppOut = 0;
}
}
/*
** Create an Fts5Iter that iterates through the doclist provided
** as the second argument.
*/
static void fts5MultiIterNew2(
| > > > > | 227056 227057 227058 227059 227060 227061 227062 227063 227064 227065 227066 227067 227068 227069 227070 227071 227072 227073 |
pNew->xSetOutputs(pNew, pSeg);
}
}else{
fts5MultiIterFree(pNew);
*ppOut = 0;
}
fts5MultiIterNew_post_check:
assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
return;
}
/*
** Create an Fts5Iter that iterates through the doclist provided
** as the second argument.
*/
static void fts5MultiIterNew2(
|
| ︙ | ︙ | |||
225434 225435 225436 225437 225438 225439 225440 |
}
/*
** Return true if the iterator is at EOF or if an error has occurred.
** False otherwise.
*/
static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
| > | | 227107 227108 227109 227110 227111 227112 227113 227114 227115 227116 227117 227118 227119 227120 227121 227122 |
}
/*
** Return true if the iterator is at EOF or if an error has occurred.
** False otherwise.
*/
static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
assert( pIter!=0 || p->rc!=SQLITE_OK );
assert( p->rc!=SQLITE_OK
|| (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof
);
return (p->rc || pIter->base.bEof);
}
/*
** Return the rowid of the entry that the iterator currently points
|
| ︙ | ︙ | |||
226238 226239 226240 226241 226242 226243 226244 226245 226246 226247 226248 226249 226250 226251 |
}
}
/* Flush the last leaf page to disk. Set the output segment b-tree height
** and last leaf page number at the same time. */
fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
if( fts5MultiIterEof(p, pIter) ){
int i;
/* Remove the redundant segments from the %_data table */
for(i=0; i<nInput; i++){
fts5DataRemoveSegment(p, pLvl->aSeg[i].iSegid);
}
| > | 227912 227913 227914 227915 227916 227917 227918 227919 227920 227921 227922 227923 227924 227925 227926 |
}
}
/* Flush the last leaf page to disk. Set the output segment b-tree height
** and last leaf page number at the same time. */
fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
assert( pIter!=0 || p->rc!=SQLITE_OK );
if( fts5MultiIterEof(p, pIter) ){
int i;
/* Remove the redundant segments from the %_data table */
for(i=0; i<nInput; i++){
fts5DataRemoveSegment(p, pLvl->aSeg[i].iSegid);
}
|
| ︙ | ︙ | |||
226338 226339 226340 226341 226342 226343 226344 |
** already occurred, this function is a no-op.
*/
static void fts5IndexAutomerge(
Fts5Index *p, /* FTS5 backend object */
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
int nLeaf /* Number of output leaves just written */
){
| | | 228013 228014 228015 228016 228017 228018 228019 228020 228021 228022 228023 228024 228025 228026 228027 |
** already occurred, this function is a no-op.
*/
static void fts5IndexAutomerge(
Fts5Index *p, /* FTS5 backend object */
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
int nLeaf /* Number of output leaves just written */
){
if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){
Fts5Structure *pStruct = *ppStruct;
u64 nWrite; /* Initial value of write-counter */
int nWork; /* Number of work-quanta to perform */
int nRem; /* Number of leaf pages left to write */
/* Update the write-counter. While doing so, set nWork. */
nWrite = pStruct->nWriteCounter;
|
| ︙ | ︙ | |||
227448 227449 227450 227451 227452 227453 227454 |
);
fts5StructureRelease(pStruct);
}
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
| > | > > | | | | > | 229123 229124 229125 229126 229127 229128 229129 229130 229131 229132 229133 229134 229135 229136 229137 229138 229139 229140 229141 229142 229143 229144 229145 |
);
fts5StructureRelease(pStruct);
}
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
if( pRet==0 ){
assert( p->rc!=SQLITE_OK );
}else{
assert( pRet->pColset==0 );
fts5IterSetOutputCb(&p->rc, pRet);
if( p->rc==SQLITE_OK ){
Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
}
}
}
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
pRet = 0;
sqlite3Fts5IndexCloseReader(p);
|
| ︙ | ︙ | |||
227700 227701 227702 227703 227704 227705 227706 |
u64 *pCksum /* IN/OUT: Checksum value */
){
int eDetail = p->pConfig->eDetail;
u64 cksum = *pCksum;
Fts5IndexIter *pIter = 0;
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
| | | 229379 229380 229381 229382 229383 229384 229385 229386 229387 229388 229389 229390 229391 229392 229393 |
u64 *pCksum /* IN/OUT: Checksum value */
){
int eDetail = p->pConfig->eDetail;
u64 cksum = *pCksum;
Fts5IndexIter *pIter = 0;
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlite3Fts5IterEof(pIter) ){
i64 rowid = pIter->iRowid;
if( eDetail==FTS5_DETAIL_NONE ){
cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
}else{
Fts5PoslistReader sReader;
for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader);
|
| ︙ | ︙ | |||
228065 228066 228067 228068 228069 228070 228071 228072 228073 228074 228075 228076 228077 228078 228079 228080 228081 |
*/
static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
Fts5Iter *pIter; /* Used to iterate through entire index */
Fts5Structure *pStruct; /* Index structure */
#ifdef SQLITE_DEBUG
/* Used by extra internal tests only run if NDEBUG is not defined */
u64 cksum3 = 0; /* Checksum based on contents of indexes */
Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
#endif
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
/* Load the FTS index structure */
pStruct = fts5StructureRead(p);
| > > > > | > < < | | | | < | 229744 229745 229746 229747 229748 229749 229750 229751 229752 229753 229754 229755 229756 229757 229758 229759 229760 229761 229762 229763 229764 229765 229766 229767 229768 229769 229770 229771 229772 229773 229774 229775 229776 229777 229778 |
*/
static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
Fts5Iter *pIter; /* Used to iterate through entire index */
Fts5Structure *pStruct; /* Index structure */
int iLvl, iSeg;
#ifdef SQLITE_DEBUG
/* Used by extra internal tests only run if NDEBUG is not defined */
u64 cksum3 = 0; /* Checksum based on contents of indexes */
Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
#endif
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
/* Load the FTS index structure */
pStruct = fts5StructureRead(p);
if( pStruct==0 ){
assert( p->rc!=SQLITE_OK );
return fts5IndexReturn(p);
}
/* Check that the internal nodes of each segment match the leaves */
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
fts5IndexIntegrityCheckSegment(p, pSeg);
}
}
/* The cksum argument passed to this function is a checksum calculated
** based on all expected entries in the FTS index (including prefix index
** entries). This block checks that a checksum calculated based on the
** actual contents of FTS index is identical.
|
| ︙ | ︙ | |||
230030 230031 230032 230033 230034 230035 230036 |
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
| > | | 231711 231712 231713 231714 231715 231716 231717 231718 231719 231720 231721 231722 231723 231724 231725 231726 |
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
if( pRowidEq!=0 ){
assert( pCsr->ePlan==FTS5_PLAN_ROWID );
sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
}else{
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
}
rc = fts5NextMethod(pCursor);
}
|
| ︙ | ︙ | |||
231448 231449 231450 231451 231452 231453 231454 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
| | | 233130 233131 233132 233133 233134 233135 233136 233137 233138 233139 233140 233141 233142 233143 233144 |
static void fts5SourceIdFunc(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
sqlite3_result_text(pCtx, "fts5: 2021-12-09 20:06:18 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882", -1, SQLITE_TRANSIENT);
}
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
|
| ︙ | ︙ | |||
231999 232000 232001 232002 232003 232004 232005 232006 232007 232008 |
ctx.pStorage = p;
ctx.iCol = -1;
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
if( pConfig->abUnindexed[iCol-1]==0 ){
const char *zText;
int nText;
if( pSeek ){
zText = (const char*)sqlite3_column_text(pSeek, iCol);
nText = sqlite3_column_bytes(pSeek, iCol);
| > > | > > | 233681 233682 233683 233684 233685 233686 233687 233688 233689 233690 233691 233692 233693 233694 233695 233696 233697 233698 233699 233700 233701 233702 233703 233704 |
ctx.pStorage = p;
ctx.iCol = -1;
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel);
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
if( pConfig->abUnindexed[iCol-1]==0 ){
const char *zText;
int nText;
assert( pSeek==0 || apVal==0 );
assert( pSeek!=0 || apVal!=0 );
if( pSeek ){
zText = (const char*)sqlite3_column_text(pSeek, iCol);
nText = sqlite3_column_bytes(pSeek, iCol);
}else if( ALWAYS(apVal) ){
zText = (const char*)sqlite3_value_text(apVal[iCol-1]);
nText = sqlite3_value_bytes(apVal[iCol-1]);
}else{
continue;
}
ctx.szCol = 0;
rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
zText, nText, (void*)&ctx, fts5StorageInsertCallback
);
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
if( p->aTotalSize[iCol-1]<0 ){
|
| ︙ | ︙ | |||
232640 232641 232642 232643 232644 232645 232646 |
static int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
int nCol = p->pConfig->nCol; /* Number of user columns in table */
sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */
int rc; /* Return Code */
assert( p->pConfig->bColumnsize );
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
| | > > > | 234326 234327 234328 234329 234330 234331 234332 234333 234334 234335 234336 234337 234338 234339 234340 234341 234342 234343 234344 234345 234346 234347 234348 234349 234350 234351 234352 234353 234354 234355 234356 |
static int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
int nCol = p->pConfig->nCol; /* Number of user columns in table */
sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */
int rc; /* Return Code */
assert( p->pConfig->bColumnsize );
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
if( pLookup ){
int bCorrupt = 1;
assert( rc==SQLITE_OK );
sqlite3_bind_int64(pLookup, 1, iRowid);
if( SQLITE_ROW==sqlite3_step(pLookup) ){
const u8 *aBlob = sqlite3_column_blob(pLookup, 0);
int nBlob = sqlite3_column_bytes(pLookup, 0);
if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){
bCorrupt = 0;
}
}
rc = sqlite3_reset(pLookup);
if( bCorrupt && rc==SQLITE_OK ){
rc = FTS5_CORRUPT;
}
}else{
assert( rc!=SQLITE_OK );
}
return rc;
}
static int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
int rc = fts5StorageLoadTotals(p, 0);
|
| ︙ | ︙ | |||
235658 235659 235660 235661 235662 235663 235664 |
}
}else{
rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
| | | 237347 237348 237349 237350 237351 237352 237353 237354 237355 237356 237357 237358 237359 237360 237361 |
}
}else{
rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
if( pCsr ){
pCsr->pFts5 = pFts5;
pCsr->pStmt = pStmt;
pCsr->aCnt = (i64*)&pCsr[1];
|
| ︙ | ︙ |
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ | | | | | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ** been edited in any way since it was last checked in, then the last ** four hexadecimal digits of the hash may be modified. ** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.38.0" #define SQLITE_VERSION_NUMBER 3038000 #define SQLITE_SOURCE_ID "2021-12-09 20:06:18 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros |
| ︙ | ︙ | |||
535 536 537 538 539 540 541 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) | < | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | #define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */ #define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) #define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8)) |
| ︙ | ︙ | |||
571 572 573 574 575 576 577 578 579 580 581 582 583 584 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ | > > > > > > > > > > > > > | 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | /* ** CAPI3REF: Flags For File Open Operations ** ** These bit values are intended for use in the ** 3rd parameter to the [sqlite3_open_v2()] interface and ** in the 4th parameter to the [sqlite3_vfs.xOpen] method. ** ** Only those flags marked as "Ok for sqlite3_open_v2()" may be ** used as the third argument to the [sqlite3_open_v2()] interface. ** The other flags have historically been ignored by sqlite3_open_v2(), ** though future versions of SQLite might change so that an error is ** raised if any of the disallowed bits are passed into sqlite3_open_v2(). ** Applications should not depend on the historical behavior. ** ** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into ** [sqlite3_open_v2()] does *not* cause the underlying database file ** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into ** [sqlite3_open_v2()] has historically be a no-op and might become an ** error in future versions of SQLite. */ #define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ |
| ︙ | ︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* | > | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | #define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */ #define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ #define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */ /* Reserved: 0x00F00000 */ /* Legacy compatibility: */ #define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ /* |
| ︙ | ︙ | |||
3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> | > > > > > > > > < < < < < < | > > > > > > > > | 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt> ** <dd>The database is opened [shared cache] disabled, overriding ** the default shared cache setting provided by ** [sqlite3_enable_shared_cache()].)^ ** ** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt> ** <dd>The database connection comes up in "extended result code mode". ** In other words, the database behaves has if ** [sqlite3_extended_result_codes(db,1)] where called on the database ** connection as soon as the connection is created. In addition to setting ** the extended result code mode, this flag also causes [sqlite3_open_v2()] ** to return an extended result code.</dd> ** ** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt> ** <dd>The database filename is not allowed to be a symbolic link</dd> ** </dl>)^ ** ** If the 3rd parameter to sqlite3_open_v2() is not one of the ** required combinations shown above optionally combined with other ** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] ** then the behavior is undefined. Historic versions of SQLite ** have silently ignored surplus bits in the flags parameter to ** sqlite3_open_v2(), however that behavior might not be carried through ** into future versions of SQLite and so applications should not rely ** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op ** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause ** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE ** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not ** by sqlite3_open_v2(). ** ** ^The fourth parameter to sqlite3_open_v2() is the name of the ** [sqlite3_vfs] object that defines the operating system interface that ** the new database connection should use. ^If the fourth parameter is ** a NULL pointer then the default [sqlite3_vfs] object is used. ** ** ^If the filename is ":memory:", then a private, temporary in-memory database |
| ︙ | ︙ | |||
6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 | ** ^The rollback callback is not invoked if a transaction is ** automatically rolled back because the database connection is closed. ** ** See also the [sqlite3_update_hook()] interface. */ SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks ** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 |
** ^The rollback callback is not invoked if a transaction is
** automatically rolled back because the database connection is closed.
**
** See also the [sqlite3_update_hook()] interface.
*/
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Autovacuum Compaction Amount Callback
** METHOD: sqlite3
**
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
** function C that is invoked prior to each autovacuum of the database
** file. ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
** the the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively. The callback should
** return the number of free pages that should be removed by the
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
** ^If the value returned is greater than or equal to the number of
** free pages, then a complete autovacuum happens.
**
** <p>^If there are multiple ATTACH-ed database files that are being
** modified as part of a transaction commit, then the autovacuum pages
** callback is invoked separately for each file.
**
** <p><b>The callback is not reentrant.</b> The callback function should
** not attempt to invoke any other SQLite interface. If it does, bad
** things may happen, including segmentation faults and corrupt database
** files. The callback function should be a simple function that
** does some arithmetic on its input parameters and returns a result.
**
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
** destructor for the P parameter. ^If X is not NULL, then X(P) is
** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection. ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled. The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong. The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
** then the default behavior is to vacuum all free pages. So, in other
** words, the default behavior is the same as if the callback function
** were something like this:
**
** <blockquote><pre>
** unsigned int demonstration_autovac_pages_callback(
** void *pClientData,
** const char *zSchema,
** unsigned int nDbPage,
** unsigned int nFreePage,
** unsigned int nBytePerPage
** ){
** return nFreePage;
** }
** </pre></blockquote>
*/
SQLITE_API int sqlite3_autovacuum_pages(
sqlite3 *db,
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
void*,
void(*)(void*)
);
/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
|
| ︙ | ︙ | |||
7851 7852 7853 7854 7855 7856 7857 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 | > | | 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 | #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_RESULT_INTREAL 27 #define SQLITE_TESTCTRL_PRNG_SEED 28 #define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29 #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 #define SQLITE_TESTCTRL_LOGEST 33 #define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, |
| ︙ | ︙ | |||
8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of | > > > > > > > > > > > > | 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 | ** ** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt> ** <dd>^This is the number of times that the prepared statement has ** been run. A single "run" for the purposes of this counter is one ** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()]. ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** ** [[SQLITE_STMTSTATUS_FILTER_MISS]] ** [[SQLITE_STMTSTATUS_FILTER HIT]] ** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br> ** SQLITE_STMTSTATUS_FILTER_MISS</dt> ** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join ** step was bypassed because a Bloom filter returned not-found. The ** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of ** times that the Bloom filter returned a find, and thus the join step ** had to be processed as normal. ** ** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt> ** <dd>^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. ** </dd> ** </dl> */ #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE_STMTSTATUS_SORT 2 #define SQLITE_STMTSTATUS_AUTOINDEX 3 #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 #define SQLITE_STMTSTATUS_FILTER_MISS 7 #define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* ** CAPI3REF: Custom Page Cache Object ** ** The sqlite3_pcache type is opaque. It is implemented by ** the pluggable module. The SQLite core has no knowledge of |
| ︙ | ︙ |
Changes to src/stash.c.
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
** Apply a stash to the current checkout.
*/
static void stash_apply(int stashid, int nConflict){
int vid;
Stmt q;
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
| | > > | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
** Apply a stash to the current checkout.
*/
static void stash_apply(int stashid, int nConflict){
int vid;
Stmt q;
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile, blob WHERE stashid=%d AND blob.uuid=stashfile.hash"
" UNION ALL SELECT 0, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile WHERE stashid=%d AND stashfile.hash IS NULL",
stashid, stashid
);
vid = db_lget_int("checkout",0);
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
filename_collation());
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
int isRemoved = db_column_int(&q, 1);
|
| ︙ | ︙ | |||
410 411 412 413 414 415 416 |
Stmt q;
Blob empty;
int bWebpage = (pCfg->diffFlags & (DIFF_WEBPAGE|DIFF_JSON|DIFF_TCL))!=0;
blob_zero(&empty);
diff_begin(pCfg);
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
| | > > | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
Stmt q;
Blob empty;
int bWebpage = (pCfg->diffFlags & (DIFF_WEBPAGE|DIFF_JSON|DIFF_TCL))!=0;
blob_zero(&empty);
diff_begin(pCfg);
db_prepare(&q,
"SELECT blob.rid, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile, blob WHERE stashid=%d AND blob.uuid=stashfile.hash"
" UNION ALL SELECT 0, isRemoved, isExec, isLink, origname, newname, delta"
" FROM stashfile WHERE stashid=%d AND stashfile.hash IS NULL",
stashid, stashid
);
while( db_step(&q)==SQLITE_ROW ){
int rid = db_column_int(&q, 0);
int isRemoved = db_column_int(&q, 1);
int isLink = db_column_int(&q, 3);
const char *zOrig = db_column_text(&q, 4);
const char *zNew = db_column_text(&q, 5);
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
390 391 392 393 394 395 396 |
a = t/fsize;
fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
}
n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
fossil_print("%*s%,d\n", colWidth, "check-ins:", n);
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
fossil_print("%*s%,d across all branches\n", colWidth, "files:", n);
| | > > | > > > < | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
a = t/fsize;
fossil_print("%*s%d:%d\n", colWidth, "compression-ratio:", a, b);
}
n = db_int(0, "SELECT COUNT(*) FROM event e WHERE e.type='ci'");
fossil_print("%*s%,d\n", colWidth, "check-ins:", n);
n = db_int(0, "SELECT count(*) FROM filename /*scan*/");
fossil_print("%*s%,d across all branches\n", colWidth, "files:", n);
n = db_int(0, "SELECT count(*) FROM ("
"SELECT DISTINCT substr(tagname,6) "
"FROM tag JOIN tagxref USING('tagid')"
" WHERE tagname GLOB 'wiki-*'"
" AND TYPEOF(tagxref.value+0)='integer'"
")");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='w'");
fossil_print("%*s%,d (%,d changes)\n", colWidth, "wiki-pages:", n, m);
n = db_int(0, "SELECT count(*) FROM tag /*scan*/"
" WHERE tagname GLOB 'tkt-*'");
m = db_int(0, "SELECT COUNT(*) FROM event WHERE type='t'");
fossil_print("%*s%,d (%,d changes)\n", colWidth, "tickets:", n, m);
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='e'");
fossil_print("%*s%,d\n", colWidth, "events:", n);
if( db_table_exists("repository","forumpost") ){
n = db_int(0, "SELECT count(*) FROM forumpost/*scan*/");
if( n>0 ){
int nThread = db_int(0, "SELECT count(*) FROM forumpost"
" WHERE froot=fpid");
fossil_print("%*s%,d (on %,d threads)\n", colWidth, "forum-posts:",
n, nThread);
}
}
n = db_int(0, "SELECT COUNT(*) FROM event WHERE type='g'");
fossil_print("%*s%,d\n", colWidth, "tag-changes:", n);
z = db_text(0, "SELECT datetime(mtime) || ' - about ' ||"
" CAST(julianday('now') - mtime AS INTEGER)"
" || ' days ago' FROM event "
" ORDER BY mtime DESC LIMIT 1");
fossil_print("%*s%s\n", colWidth, "latest-change:", z);
|
| ︙ | ︙ |
Changes to src/style.chat.css.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
padding: 0.25em 0.5em;
margin-top: 0;
min-width: 9em /*avoid unsightly "underlap" with the neighboring
.message-widget-tab element*/;
white-space: normal;
}
body.chat.monospace-messages .message-widget-content,
| < < | > > > > > > > > > > > > > > > > > > > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
padding: 0.25em 0.5em;
margin-top: 0;
min-width: 9em /*avoid unsightly "underlap" with the neighboring
.message-widget-tab element*/;
white-space: normal;
}
body.chat.monospace-messages .message-widget-content,
body.chat.monospace-messages .chat-input-field{
font-family: monospace;
}
body.chat .message-widget-content > * {
margin: 0;
padding: 0;
}
body.chat .message-widget-content > pre {
white-space: pre-wrap;
}
body.chat .message-widget-content > .markdown > *:first-child {
margin-top: 0;
}
body.chat .message-widget-content > .markdown > *:last-child {
margin-bottom: 0;
}
body.chat .message-widget-content.error .buttons {
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
body.chat .message-widget-content.error .buttons > button {
margin: 0.25em;
}
body.chat .message-widget-content.error a {
color: inherit;
}
body.chat .message-widget-content.error .failed-message {
display: flex;
flex-direction: column;
}
body.chat .message-widget-content.error .failed-message textarea {
min-height: 5rem;
}
/* User name and timestamp (a LEGEND-like element) */
body.chat .message-widget .message-widget-tab {
border-radius: 0.25em 0.25em 0 0;
margin: 0 0.25em 0em 0.15em;
padding: 0 0.5em 0.15em 0.5em;
cursor: pointer;
white-space: nowrap;
|
| ︙ | ︙ | |||
179 180 181 182 183 184 185 |
}
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
| | < < > > | > | > > > > > > > > > > > | | | | | | | | | | | | < | > | | < | | | | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
}
body.chat:not(.chat-only-mode) #chat-input-area{
/* Safari user reports that 2em is necessary to keep the file selection
widget from overlapping the page footer, whereas a margin of 0 is fine
for FF/Chrome (and 2em is a *huge* waste of space for those). */
margin-bottom: 0;
}
.chat-input-field {
flex: 10 1 auto;
margin: 0;
}
#chat-input-field-x,
#chat-input-field-multi {
overflow: auto;
resize: vertical;
}
#chat-input-field-x {
display: inline-block/*supposed workaround for Chrome weirdness*/;
padding: 0.2em;
background-color: rgba(156,156,156,0.3);
white-space: pre-wrap;
/* ^^^ Firefox, when pasting plain text into a contenteditable field,
loses all newlines unless we explicitly set this. Chrome does not. */
cursor: text;
/* ^^^ In some browsers the cursor may not change for a contenteditable
element until it has focus, causing potential confusion. */
}
#chat-input-field-x:empty::before {
content: attr(data-placeholder);
opacity: 0.6;
}
.chat-input-field:not(:focus){
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
}
.chat-input-field:focus{
/* This transparent border helps avoid the text shifting around
when the contenteditable attribute causes a border (which we
apparently cannot style) to be added. */
border-width: 1px;
border-style: solid;
border-color: transparent;
border-radius: 0.25em;
}
/* Widget holding the chat message input field, send button, and
settings button. */
body.chat #chat-input-line-wrapper {
display: flex;
flex-direction: row;
align-items: stretch;
flex-wrap: nowrap;
}
/*body.chat #chat-input-line-wrapper:not(.compact) {
flex-wrap: nowrap;
}*/
body.chat #chat-input-line-wrapper.compact {
/* "The problem" with wrapping, together with a contenteditable input
field, is that the latter grows as the user types, so causes
wrapping to happen while they type, then to unwrap as soon as the
input field is cleared (when the message is sent). When we stay
wrapped in compact mode, the wrapped buttons simply take up too
much space. */
/*flex-wrap: wrap;
justify-content: flex-end;*/
flex-direction: column;
/**
We "really do" need column orientation here because it's the
only way to eliminate the possibility that (A) the buttons
get truncated in very narrow windows and (B) that they keep
stable positions.
*/
}
body.chat #chat-input-line-wrapper.compact #chat-input-field-x {
}
body.chat #chat-buttons-wrapper {
flex: 0 1 auto;
display: flex;
flex-direction: column;
align-items: center;
min-width: 4em;
min-height: 1.5em;
align-self: flex-end
/*keep buttons stable at bottom/right even when input field
resizes */;
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper {
flex-direction: row;
flex: 1 1 auto;
align-self: stretch;
justify-content: flex-end;
/*flex-wrap: wrap;*/
/* Wrapping would be ideal except that the edit widget
grows in width as the user types, moving the buttons
around */
}
body.chat #chat-buttons-wrapper > .cbutton {
padding: 0;
display: inline-block;
border-width: 1px;
border-style: solid;
border-radius: 0.25em;
min-width: 4ex;
max-width: 4ex;
min-height: 3ex;
max-height: 3ex;
margin: 0.125em;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 130%;
}
body.chat #chat-buttons-wrapper > .cbutton:hover {
background-color: rgba(200,200,200,0.3);
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper > .cbutton {
margin: 2px 0.125em 0 0.125em;
min-width: 6ex;
max-width: 6ex;
min-height: 2.3ex;
max-height: 2.3ex;
font-size: 120%;
}
body.chat #chat-input-line-wrapper.compact #chat-buttons-wrapper #chat-button-submit {
min-width: 12ex;
}
.chat-input-field {
font-family: inherit
}
body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-multi,
body.chat #chat-input-line-wrapper:not(.compact) #chat-input-field-x {
min-height: 4rem;
/*
Problems related to max-height:
- If we do NOT set a max-height then pasting/typing a large amount
of text can cause this element to grow without bounds, larger than
the window, and there's no way to navigate it sensibly. In this
case, manually resizing the element (desktop only - mobile doesn't
offer that) will force it to stay at the selected size even if more
content is added to it later.
- If we DO set a max-height then its growth is bounded but it also
cannot manually expanded by the user.
The lesser of the two evils seems to be to rely on the browser
feature that a manual resize of the element will pin its size.
*/
}
body.chat #chat-input-line-wrapper > #chat-button-settings{
margin: 0 0 0 0.25em;
max-width: 2em;
}
body.chat #chat-input-line-wrapper > input[type=text],
body.chat #chat-input-line-wrapper > textarea {
flex: 20 1 auto;
max-width: revert;
min-width: 20em;
}
body.chat #chat-input-line-wrapper.compact > input[type=text] {
margin: 0 0 0.25em 0/* gap for if/when buttons wrap*/;
}
/* Widget holding the file selection control and preview */
body.chat #chat-input-file-area {
display: flex;
flex-direction: row;
margin: 0;
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 |
body.chat #chat-drop-details {
padding: 0 1em;
white-space: pre;
font-family: monospace;
margin: auto;
flex: 0;
}
| > > > | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 |
body.chat #chat-drop-details {
padding: 0 1em;
white-space: pre;
font-family: monospace;
margin: auto;
flex: 0;
}
body.chat #chat-drop-details:empty {
padding: 0;
margin: 0;
}
body.chat #chat-drop-details img {
max-width: 45%;
max-height: 45%;
}
body.chat .chat-view {
flex: 20 1 auto
/*ensure that these grow more than the non-.chat-view elements.
|
| ︙ | ︙ | |||
387 388 389 390 391 392 393 394 395 396 |
}
body.chat #chat-config #chat-config-options {
/* /chat config options go here */
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: auto;
}
body.chat #chat-config #chat-config-options .menu-entry {
display: flex;
| > | | > > | > > > > > > > > | | > > > > > > > > > > > > | > > > > > > > > > > > > > > > | > < < < < | < < < | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
}
body.chat #chat-config #chat-config-options {
/* /chat config options go here */
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: auto;
align-items: stretch;
}
body.chat #chat-config #chat-config-options .menu-entry {
display: flex;
align-items: center;
flex-direction: row-reverse;
flex-wrap: nowrap;
padding: 1em;
flex: 1 1 auto;
align-self: stretch;
}
body.chat #chat-config #chat-config-options .menu-entry.parent{
border-radius: 1em 1em 0 1em;
margin-top: 1em;
}
body.chat #chat-config #chat-config-options .menu-entry.child {
/*padding-left: 2.5em;*/
margin-left: 2em;
}
body.chat #chat-config #chat-config-options .menu-entry:nth-of-type(even){
background-color: rgba(175,175,175,0.15);
}
body.chat #chat-config #chat-config-options .menu-entry:nth-of-type(odd){
background-color: rgba(175,175,175,0.35);
}
body.chat #chat-config #chat-config-options .menu-entry:first-child {
/* Config list header */
border-radius: 0 0 1em 1em;
}
body.chat #chat-config #chat-config-options .menu-entry:first-child .label-wrapper {
align-items: start;
}
body.chat #chat-config #chat-config-options .menu-entry > .toggle-wrapper {
/* Holder for a checkbox, if any */
min-width: 1.5rem;
margin-right: 1rem;
}
body.chat #chat-config #chat-config-options .menu-entry .label-wrapper {
/* Wrapper for a LABEL and a .hint element. */
display: flex;
flex-direction: column;
align-self: baseline;
flex: 1 1 auto;
}
body.chat #chat-config #chat-config-options .menu-entry label {
/* Config option label. */
font-weight: bold;
white-space: initial;
}
body.chat #chat-config #chat-config-options .menu-entry label[for] {
cursor: pointer;
}
body.chat #chat-config #chat-config-options .menu-entry .hint {
/* Config menu hint text */
font-size: 85%;
font-weight: normal;
white-space: pre-wrap;
display: inline-block;
opacity: 0.85;
}
body.chat #chat-config #chat-config-options .menu-entry select {
}
body.chat #chat-preview #chat-preview-content {
overflow: auto;
flex: 1 1 auto;
padding: 0.5em;
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ******************************************************************************* ** ** This file contains code used to push, pull, and sync a repository */ #include "config.h" #include "sync.h" #include <assert.h> /* ** If the repository is configured for autosyncing, then do an ** autosync. Bits of the "flags" parameter determine details of behavior: ** ** SYNC_PULL Pull content from the server to the local repo ** SYNC_PUSH Push content from local up to the server | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
*******************************************************************************
**
** This file contains code used to push, pull, and sync a repository
*/
#include "config.h"
#include "sync.h"
#include <assert.h>
/*
** Explain what type of sync operation is about to occur
*/
static void sync_explain(unsigned syncFlags){
if( g.url.isAlias ){
if( (syncFlags & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
fossil_print("Sync with %s\n", g.url.canonical);
}else if( syncFlags & SYNC_PUSH ){
fossil_print("Push to %s\n", g.url.canonical);
}else if( syncFlags & SYNC_PULL ){
fossil_print("Pull from %s\n", g.url.canonical);
}
}
}
/*
** Call client_sync() one or more times in order to complete a
** sync operation. Usually, client_sync() is called only once, though
** is can be called multiple times if the SYNC_ALLURL flags is set.
*/
static int client_sync_all_urls(
unsigned syncFlags, /* Mask of SYNC_* flags */
unsigned configRcvMask, /* Receive these configuration items */
unsigned configSendMask, /* Send these configuration items */
const char *zAltPCode /* Alternative project code (usually NULL) */
){
int nErr;
int nOther;
char **azOther;
int i;
Stmt q;
sync_explain(syncFlags);
nErr = client_sync(syncFlags, configRcvMask, configSendMask, zAltPCode);
if( nErr==0 ) url_remember();
if( (syncFlags & SYNC_ALLURL)==0 ) return nErr;
nOther = 0;
azOther = 0;
db_prepare(&q,
"SELECT substr(name,10) FROM config"
" WHERE name glob 'sync-url:*'"
" AND value<>(SELECT value FROM config WHERE name='last-sync-url')"
);
while( db_step(&q)==SQLITE_ROW ){
const char *zUrl = db_column_text(&q, 0);
azOther = fossil_realloc(azOther, sizeof(*azOther)*(nOther+1));
azOther[nOther++] = fossil_strdup(zUrl);
}
db_finalize(&q);
for(i=0; i<nOther; i++){
int rc;
url_unparse(&g.url);
url_parse(azOther[i], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
sync_explain(syncFlags);
rc = client_sync(syncFlags, configRcvMask, configSendMask, zAltPCode);
nErr += rc;
if( (g.url.flags & URL_REMEMBER_PW)!=0 && rc==0 ){
char *zKey = mprintf("sync-pw:%s", azOther[i]);
char *zPw = obscure(g.url.passwd);
if( zPw && zPw[0] ){
db_set(zKey/*works-like:""*/, zPw, 0);
}
fossil_free(zPw);
fossil_free(zKey);
}
fossil_free(azOther[i]);
azOther[i] = 0;
}
fossil_free(azOther);
return nErr;
}
/*
** If the repository is configured for autosyncing, then do an
** autosync. Bits of the "flags" parameter determine details of behavior:
**
** SYNC_PULL Pull content from the server to the local repo
** SYNC_PUSH Push content from local up to the server
|
| ︙ | ︙ | |||
46 47 48 49 50 51 52 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get("autosync", 0);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
| | > > > > > > | | < | | > | 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get("autosync", 0);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
if( db_get_boolean("dont-push",0)
|| sqlite3_strglob("*pull*", zAutosync)==0
){
flags &= ~SYNC_CKIN_LOCK;
if( flags & SYNC_PUSH ) return 0;
}
if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
url_parse(0, URL_REMEMBER);
if( g.url.protocol==0 ) return 0;
if( g.url.user!=0 && g.url.passwd==0 ){
g.url.passwd = unobscure(db_get("last-sync-pw", 0));
g.url.flags |= URL_PROMPT_PW;
url_prompt_for_password();
}
g.zHttpAuth = get_httpauth();
if( sqlite3_strglob("*all*", zAutosync)==0 ){
rc = client_sync_all_urls(flags|SYNC_ALLURL, configSync, 0, 0);
}else{
url_remember();
sync_explain(flags);
url_enable_proxy("via proxy: ");
rc = client_sync(flags, configSync, 0, 0);
}
return rc;
}
/*
** This routine will try a number of times to perform autosync with a
** 0.5 second sleep between attempts.
**
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
}
if( find_option("verbose","v",0)!=0 ){
*pSyncFlags |= SYNC_VERBOSE;
}
if( find_option("no-http-compression",0,0)!=0 ){
*pSyncFlags |= SYNC_NOHTTPCOMPRESS;
}
url_proxy_options();
clone_ssh_find_options();
if( !uvOnly ) db_find_and_open_repository(0, 0);
db_open_config(0, 1);
if( g.argc==2 ){
if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN;
}else if( g.argc==3 ){
zUrl = g.argv[2];
}
if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
&& db_get_boolean("uv-sync",0)
){
*pSyncFlags |= SYNC_UNVERSIONED;
}
urlFlags &= ~urlOmitFlags;
if( urlFlags & URL_REMEMBER ){
clone_ssh_db_set_options();
}
url_parse(zUrl, urlFlags);
remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl);
| > > > > > > > < < < < < < < < < < > > | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
}
if( find_option("verbose","v",0)!=0 ){
*pSyncFlags |= SYNC_VERBOSE;
}
if( find_option("no-http-compression",0,0)!=0 ){
*pSyncFlags |= SYNC_NOHTTPCOMPRESS;
}
if( find_option("all",0,0)!=0 ){
*pSyncFlags |= SYNC_ALLURL;
}
url_proxy_options();
clone_ssh_find_options();
if( !uvOnly ) db_find_and_open_repository(0, 0);
db_open_config(0, 1);
if( g.argc==2 ){
if( db_get_boolean("auto-shun",0) ) configSync = CONFIGSET_SHUN;
}else if( g.argc==3 ){
zUrl = g.argv[2];
if( (*pSyncFlags) & SYNC_ALLURL ){
fossil_fatal("cannot use both the --all option and specific URL \"%s\"",
zUrl);
}
}
if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
&& db_get_boolean("uv-sync",0)
){
*pSyncFlags |= SYNC_UNVERSIONED;
}
urlFlags &= ~urlOmitFlags;
if( urlFlags & URL_REMEMBER ){
clone_ssh_db_set_options();
}
url_parse(zUrl, urlFlags);
remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl);
if( g.url.protocol==0 ){
if( urlOptional ) fossil_exit(0);
usage("URL");
}
user_select();
url_enable_proxy("via proxy: ");
*pConfigFlags |= configSync;
}
/*
** COMMAND: pull
**
** Usage: %fossil pull ?URL? ?options?
**
** Pull all sharable changes from a remote repository into the local
** repository. Sharable changes include public check-ins, edits to
** wiki pages, tickets, tech-notes, and forum posts. Add
** the --private option to pull private branches. Use the
** "configuration pull" command to pull website configuration details.
**
** If URL is not specified, then the URL from the most recent clone, push,
** pull, remote, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** --all Pull from all remotes, not just the default
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --from-parent-project Pull content from the parent project
** --ipv4 Use only IPv4, not IPv6
** --no-http-compression Do not compress HTTP traffic
** --once Do not remember URL for subsequent syncs
** --private Pull private branches too
|
| ︙ | ︙ | |||
235 236 237 238 239 240 241 | } if( zAltPCode ) urlOmitFlags = URL_REMEMBER; process_sync_args(&configFlags, &syncFlags, 0, urlOmitFlags); /* We should be done with options.. */ verify_all_options(); | | > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | } if( zAltPCode ) urlOmitFlags = URL_REMEMBER; process_sync_args(&configFlags, &syncFlags, 0, urlOmitFlags); /* We should be done with options.. */ verify_all_options(); client_sync_all_urls(syncFlags, configFlags, 0, zAltPCode); } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ** Push all sharable changes from the local repository to a remote ** repository. Sharable changes include public check-ins, edits to ** wiki pages, tickets, tech-notes, and forum posts. Use ** --private to also push private branches. Use the "configuration ** push" command to push website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ** ** --all Push to all remotes, not just the default ** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol, ** if required by the remote website ** --ipv4 Use only IPv4, not IPv6 ** --no-http-compression Do not compress HTTP traffic ** --once Do not remember URL for subsequent syncs ** --proxy PROXY Use the specified HTTP proxy ** --private Push private branches too |
| ︙ | ︙ | |||
282 283 284 285 286 287 288 |
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ){
fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
}
| | > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ){
fossil_fatal("pushing is prohibited: the 'dont-push' option is set");
}
client_sync_all_urls(syncFlags, 0, 0, 0);
}
/*
** COMMAND: sync
**
** Usage: %fossil sync ?URL? ?options?
**
** Synchronize all sharable changes between the local repository and a
** remote repository. Sharable changes include public check-ins and
** edits to wiki pages, tickets, forum posts, and technical notes.
**
** If URL is not specified, then the URL from the most recent clone, push,
** pull, remote, or sync command is used. See "fossil help clone" for
** details on the URL formats.
**
** Options:
**
** --all Sync with all remotes, not just the default
** -B|--httpauth USER:PASS Credentials for the simple HTTP auth protocol,
** if required by the remote website
** --ipv4 Use only IPv4, not IPv6
** --no-http-compression Do not compress HTTP traffic
** --once Do not remember URL for subsequent syncs
** --proxy PROXY Use the specified HTTP proxy
** --private Sync private branches too
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 |
}
process_sync_args(&configFlags, &syncFlags, 0, 0);
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
| < > | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
}
process_sync_args(&configFlags, &syncFlags, 0, 0);
/* We should be done with options.. */
verify_all_options();
if( db_get_boolean("dont-push",0) ) syncFlags &= ~SYNC_PUSH;
if( (syncFlags & SYNC_PUSH)==0 ){
fossil_warning("pull only: the 'dont-push' option is set");
}
client_sync_all_urls(syncFlags, configFlags, 0, 0);
}
/*
** Handle the "fossil unversioned sync" and "fossil unversioned revert"
** commands.
*/
void sync_unversioned(unsigned syncFlags){
|
| ︙ | ︙ | |||
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
** Forget the default sync URL, disabling autosync. Combined with
** named sync URLs, it allows canceling this "airplane mode" with
** "fossil remote NAME" to select a previously-set named URL.
**
** To disable use of the default remote without forgetting its URL,
** say "fossil set autosync 0" instead.
**
** > fossil remote REF
**
** Make REF the new default URL, replacing the prior default.
** REF may be a URL or a NAME from a prior "add".
*/
void remote_url_cmd(void){
char *zUrl, *zArg;
int nArg;
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
if( g.argc==2 ){
/* "fossil remote" with no arguments: Show the last sync URL. */
zUrl = db_get("last-sync-url", 0);
if( zUrl==0 ){
fossil_print("off\n");
}else{
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
** Forget the default sync URL, disabling autosync. Combined with
** named sync URLs, it allows canceling this "airplane mode" with
** "fossil remote NAME" to select a previously-set named URL.
**
** To disable use of the default remote without forgetting its URL,
** say "fossil set autosync 0" instead.
**
** > fossil remote scrub
**
** Forget any saved passwords for remote repositories, but continue
** to remember the URLs themselves. You will be prompted for the
** password the next time it is needed.
**
** > fossil remote REF
**
** Make REF the new default URL, replacing the prior default.
** REF may be a URL or a NAME from a prior "add".
*/
void remote_url_cmd(void){
char *zUrl, *zArg;
int nArg;
db_find_and_open_repository(0, 0);
/* We should be done with options.. */
verify_all_options();
/* 2021-10-25: A note about data structures.
**
** The remote URLs are stored in the CONFIG table. The URL is stored
** separately from the password. The password is obscured using the
** obscure() function.
**
** Originally, Fossil only preserved a single remote URL. That URL
** is stored in "last-sync-url" and the password in "last-sync-pw". The
** ability to have multiple remotes was added later so these names
** were retained for backwards compatibility. The other remotes are
** stored in "sync-url:NAME" and "sync-pw:NAME" where NAME is the name
** of the remote.
**
** The last-sync-url is called "default" for the display list.
**
** The last-sync-url might be duplicated into one of the sync-url:NAME
** entries. Thus, when doing a "fossil sync --all" or an autosync with
** autosync=all, each sync-url:NAME entry is checked to see if it is the
** same as last-sync-url and if it is then that entry is skipped.
*/
if( g.argc==2 ){
/* "fossil remote" with no arguments: Show the last sync URL. */
zUrl = db_get("last-sync-url", 0);
if( zUrl==0 ){
fossil_print("off\n");
}else{
|
| ︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 |
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
db_protect_pop();
db_commit_transaction();
return;
}
if( sqlite3_strlike("http://%",zArg,0)==0
|| sqlite3_strlike("https://%",zArg,0)==0
|| sqlite3_strlike("ssh:%",zArg,0)==0
|| sqlite3_strlike("file:%",zArg,0)==0
|| db_exists("SELECT 1 FROM config WHERE name='sync-url:%q'",zArg)
){
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 |
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
db_protect_pop();
db_commit_transaction();
return;
}
if( strncmp(zArg, "scrub", nArg)==0 ){
if( g.argc!=3 ) usage("scrub");
db_begin_write();
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:*'");
db_multi_exec("DELETE FROM config WHERE name = 'last-sync-pw'");
db_protect_pop();
db_commit_transaction();
return;
}
if( strncmp(zArg, "config-data", nArg)==0 ){
/* Undocumented command: "fossil remote config-data"
**
** Show the CONFIG table entries that relate to remembering remote URLs
*/
Stmt q;
int n;
n = db_int(13,
"SELECT max(length(name))"
" FROM config"
" WHERE name GLOB 'sync-*:*' OR name GLOB 'last-sync-*'"
);
db_prepare(&q,
"SELECT name,"
" CASE WHEN name LIKE '%%sync-pw%%'"
" THEN printf('%%.*c',length(value),'*') ELSE value END"
" FROM config"
" WHERE name GLOB 'sync-*:*' OR name GLOB 'last-sync-*'"
" ORDER BY name LIKE '%%sync-pw%%', name"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%-*s %s\n",
n, db_column_text(&q,0),
db_column_text(&q,1)
);
}
db_finalize(&q);
return;
}
if( sqlite3_strlike("http://%",zArg,0)==0
|| sqlite3_strlike("https://%",zArg,0)==0
|| sqlite3_strlike("ssh:%",zArg,0)==0
|| sqlite3_strlike("file:%",zArg,0)==0
|| db_exists("SELECT 1 FROM config WHERE name='sync-url:%q'",zArg)
){
|
| ︙ | ︙ |
Changes to src/tktsetup.c.
| ︙ | ︙ | |||
535 536 537 538 539 540 541 542 543 544 545 |
@ if {$seenRow} {
@ html "<hr />\n"
@ } else {
@ html "<tr><td class='tktDspLabel'>User Comments:</td></tr>\n"
@ html "<tr><td colspan='5' class='tktDspValue'>\n"
@ set seenRow 1
@ }
@ html "[htmlize $xlogin]"
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
@ html " (claiming to be [htmlize $xusername])"
@ }
| > | > | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
@ if {$seenRow} {
@ html "<hr />\n"
@ } else {
@ html "<tr><td class='tktDspLabel'>User Comments:</td></tr>\n"
@ html "<tr><td colspan='5' class='tktDspValue'>\n"
@ set seenRow 1
@ }
@ html "<span class='tktDspCommenter'>"
@ html "[htmlize $xlogin]"
@ if {$xlogin ne $xusername && [string length $xusername]>0} {
@ html " (claiming to be [htmlize $xusername])"
@ }
@ html " added on $xdate:"
@ html "</span>\n"
@ if {$alwaysPlaintext || $xmimetype eq "text/plain"} {
@ set r [randhex]
@ if {$xmimetype ne "text/plain"} {html "([htmlize $xmimetype])\n"}
@ wiki "<verbatim-$r>[string trimright $xcomment]</verbatim-$r>\n"
@ } elseif {$xmimetype eq "text/x-fossil-wiki"} {
@ wiki "<p>\n[string trimright $xcomment]\n</p>\n"
@ } elseif {$xmimetype eq "text/x-markdown"} {
|
| ︙ | ︙ |
Changes to src/unversioned.c.
| ︙ | ︙ | |||
655 656 657 658 659 660 661 |
void uvlist_json_page(void){
Stmt q;
char *zSep = "[";
Blob json;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
| | | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
void uvlist_json_page(void){
Stmt q;
char *zSep = "[";
Blob json;
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
cgi_set_content_type("application/json");
etag_check(ETAG_DATA,0);
if( !db_table_exists("repository","unversioned") ){
blob_init(&json, "[]", -1);
cgi_set_content(&json);
return;
}
blob_init(&json, 0, 0);
|
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
42 43 44 45 46 47 48 |
#define URL_PROMPTED 0x010 /* Prompted for PW already */
#define URL_OMIT_USER 0x020 /* Omit the user name from URL */
/*
** The URL related data used with this subsystem.
*/
struct UrlData {
| | | | | | | | | | | | | | | | | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#define URL_PROMPTED 0x010 /* Prompted for PW already */
#define URL_OMIT_USER 0x020 /* Omit the user name from URL */
/*
** The URL related data used with this subsystem.
*/
struct UrlData {
int isFile; /* True if a "file:" url */
int isHttps; /* True if a "https:" url */
int isSsh; /* True if an "ssh:" url */
int isAlias; /* Input URL was an alias */
char *name; /* Hostname for http: or filename for file: */
char *hostname; /* The HOST: parameter on http headers */
const char *protocol; /* "http" or "https" or "ssh" or "file" */
int port; /* TCP port number for http: or https: */
int dfltPort; /* The default port for the given protocol */
char *path; /* Pathname for http: */
char *user; /* User id for http: */
char *passwd; /* Password for http: */
char *canonical; /* Canonical representation of the URL */
char *proxyAuth; /* Proxy-Authorizer: string */
char *fossil; /* The fossil query parameter on ssh: */
unsigned flags; /* Boolean flags controlling URL processing */
int useProxy; /* Used to remember that a proxy is in use */
char *proxyUrlPath;
int proxyOrigPort; /* Tunneled port number for https through proxy */
};
#endif /* INTERFACE */
/*
** Parse the given URL. Or if zUrl is NULL, parse the URL in the
** last-sync-url setting using last-sync-pw as the password. Store
|
| ︙ | ︙ | |||
139 140 141 142 143 144 145 |
pUrlData->protocol = "https";
pUrlData->dfltPort = 443;
iStart = 8;
}else if( zUrl[0]=='s' ){
pUrlData->isSsh = 1;
pUrlData->protocol = "ssh";
pUrlData->dfltPort = 22;
| | | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
pUrlData->protocol = "https";
pUrlData->dfltPort = 443;
iStart = 8;
}else if( zUrl[0]=='s' ){
pUrlData->isSsh = 1;
pUrlData->protocol = "ssh";
pUrlData->dfltPort = 22;
pUrlData->fossil = fossil_strdup("fossil");
iStart = 6;
}else{
pUrlData->isHttps = 0;
pUrlData->protocol = "http";
pUrlData->dfltPort = 80;
iStart = 7;
}
|
| ︙ | ︙ | |||
224 225 226 227 228 229 230 |
while( pUrlData->path[i] && pUrlData->path[i]!='&' ){ i++; }
}
if( pUrlData->path[i] ){
pUrlData->path[i] = 0;
i++;
}
if( fossil_strcmp(zName,"fossil")==0 ){
| | | > > > > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
while( pUrlData->path[i] && pUrlData->path[i]!='&' ){ i++; }
}
if( pUrlData->path[i] ){
pUrlData->path[i] = 0;
i++;
}
if( fossil_strcmp(zName,"fossil")==0 ){
pUrlData->fossil = fossil_strdup(zValue);
dehttpize(pUrlData->fossil);
fossil_free(zExe);
zExe = mprintf("%cfossil=%T", cQuerySep, pUrlData->fossil);
cQuerySep = '&';
}
}
dehttpize(pUrlData->path);
if( pUrlData->dfltPort==pUrlData->port ){
pUrlData->canonical = mprintf(
"%s://%s%T%T%z",
pUrlData->protocol, zLogin, pUrlData->name, pUrlData->path, zExe
);
}else{
pUrlData->canonical = mprintf(
"%s://%s%T:%d%T%z",
pUrlData->protocol, zLogin, pUrlData->name, pUrlData->port,
pUrlData->path, zExe
);
}
if( pUrlData->isSsh && pUrlData->path[1] ){
char *zOld = pUrlData->path;
pUrlData->path = mprintf("%s", zOld+1);
fossil_free(zOld);
}
free(zLogin);
}else if( strncmp(zUrl, "file:", 5)==0 ){
pUrlData->isFile = 1;
if( zUrl[5]=='/' && zUrl[6]=='/' ){
i = 7;
}else{
i = 5;
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
if( pUrlData->isFile ){
Blob cfile;
dehttpize(zFile);
file_canonical_name(zFile, &cfile, 0);
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
| | | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
if( pUrlData->isFile ){
Blob cfile;
dehttpize(zFile);
file_canonical_name(zFile, &cfile, 0);
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
pUrlData->path = mprintf("");
pUrlData->name = mprintf("%b", &cfile);
pUrlData->canonical = mprintf("file://%T", pUrlData->name);
blob_reset(&cfile);
}else if( pUrlData->user!=0 && pUrlData->passwd==0
&& (urlFlags & URL_PROMPT_PW)!=0 ){
url_prompt_for_password_local(pUrlData);
}else if( pUrlData->user!=0 && ( urlFlags & URL_ASK_REMEMBER_PW ) ){
|
| ︙ | ︙ | |||
308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
p = &g.url;
}
fossil_free(p->canonical);
fossil_free(p->name);
fossil_free(p->path);
fossil_free(p->user);
fossil_free(p->passwd);
memset(p, 0, sizeof(*p));
}
/*
** Parse the given URL, which describes a sync server. Populate variables
** in the global "g.url" structure as shown below. If zUrl is NULL, then
** parse the URL given in the last-sync-url setting, taking the password
| > | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
p = &g.url;
}
fossil_free(p->canonical);
fossil_free(p->name);
fossil_free(p->path);
fossil_free(p->user);
fossil_free(p->passwd);
fossil_free(p->fossil);
memset(p, 0, sizeof(*p));
}
/*
** Parse the given URL, which describes a sync server. Populate variables
** in the global "g.url" structure as shown below. If zUrl is NULL, then
** parse the URL given in the last-sync-url setting, taking the password
|
| ︙ | ︙ | |||
597 598 599 600 601 602 603 |
void url_prompt_for_password_local(UrlData *pUrlData){
if( pUrlData->isSsh || pUrlData->isFile ) return;
if( isatty(fileno(stdin))
&& (pUrlData->flags & URL_PROMPT_PW)!=0
&& (pUrlData->flags & URL_PROMPTED)==0
){
pUrlData->flags |= URL_PROMPTED;
| | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
void url_prompt_for_password_local(UrlData *pUrlData){
if( pUrlData->isSsh || pUrlData->isFile ) return;
if( isatty(fileno(stdin))
&& (pUrlData->flags & URL_PROMPT_PW)!=0
&& (pUrlData->flags & URL_PROMPTED)==0
){
pUrlData->flags |= URL_PROMPTED;
pUrlData->passwd = prompt_for_user_password(pUrlData->canonical);
if( pUrlData->passwd[0]
&& (pUrlData->flags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
){
if( save_password_prompt(pUrlData->passwd) ){
pUrlData->flags |= URL_REMEMBER_PW;
}else{
pUrlData->flags &= ~URL_REMEMBER_PW;
|
| ︙ | ︙ |
Changes to src/user.c.
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
/*
** Prompt to save Fossil user password
*/
int save_password_prompt(const char *passwd){
Blob x;
char c;
| < < < < | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
/*
** Prompt to save Fossil user password
*/
int save_password_prompt(const char *passwd){
Blob x;
char c;
if( fossil_security_level()>=1 ) return 0;
prompt_user("remember password (Y/n)? ", &x);
c = blob_str(&x)[0];
blob_reset(&x);
return ( c!='n' && c!='N' );
}
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
209 210 211 212 213 214 215 |
int w, h;
char *zOut = pikchr(zPikchr, "pikchr", 0, &w, &h);
if( w>0 ){
@ <div class="pikchr-svg" style="max-width:%d(w)px">
@ %s(zOut)
@ </div>
}else{
| | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
int w, h;
char *zOut = pikchr(zPikchr, "pikchr", 0, &w, &h);
if( w>0 ){
@ <div class="pikchr-svg" style="max-width:%d(w)px">
@ %s(zOut)
@ </div>
}else{
@ <pre class='error'>
@ %h(zOut)
@ </pre>
}
free(zOut);
}else{
@ <pre class='textPlain'>
@ %h(blob_str(pWiki))
@ </pre>
|
| ︙ | ︙ | |||
664 665 666 667 668 669 670 |
}
/*
** Given a mimetype, return its common name.
*/
static const char *mimetype_common_name(const char *zMimetype){
int i;
| | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
}
/*
** Given a mimetype, return its common name.
*/
static const char *mimetype_common_name(const char *zMimetype){
int i;
for(i=6; i>=0; i-=3){
if( zMimetype && fossil_strcmp(zMimetype, azStyles[i])==0 ){
return azStyles[i+1];
}
}
return azStyles[1];
}
|
| ︙ | ︙ | |||
1590 1591 1592 1593 1594 1595 1596 |
** URL: /wikiappend?name=PAGENAME&mimetype=MIMETYPE
**
** Append text to the end of a wiki page.
*/
void wikiappend_page(void){
char *zTag;
int rid = 0;
| < > > > > > > | > | < | < < > | < < < < < < | < < | < < | | | | | | | | | | | | | | | | | | | | | | | < > > | > > > > > | | 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 |
** URL: /wikiappend?name=PAGENAME&mimetype=MIMETYPE
**
** Append text to the end of a wiki page.
*/
void wikiappend_page(void){
char *zTag;
int rid = 0;
const char *zPageName;
const char *zUser;
const char *zMimetype;
int goodCaptcha = 1;
const char *zFormat;
Manifest *pWiki = 0;
int isSandbox;
login_check_credentials();
if( !g.perm.ApndWiki ){
login_needed(g.anon.ApndWiki);
return;
}
zPageName = PD("name","");
zMimetype = wiki_filter_mimetypes(P("mimetype"));
if( check_name(zPageName) ) return;
isSandbox = is_sandbox(zPageName);
if(!isSandbox){
zTag = mprintf("wiki-%s", zPageName);
rid = db_int(0,
"SELECT rid FROM tagxref"
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
" ORDER BY mtime DESC", zTag
);
free(zTag);
pWiki = rid ? manifest_get(rid, CFTYPE_WIKI, 0) : 0;
if( !pWiki ){
fossil_redirect_home();
return;
}
zMimetype = wiki_filter_mimetypes(pWiki->zMimetype)
/* see https://fossil-scm.org/forum/forumpost/0acfdaac80 */;
}
if( !isSandbox && P("submit")!=0 && P("r")!=0 && P("u")!=0
&& (goodCaptcha = captcha_is_correct(0))
){
char *zDate;
Blob cksum;
Blob body;
Blob wiki;
blob_zero(&body);
login_verify_csrf_secret();
blob_append(&body, pWiki->zWiki, -1);
blob_zero(&wiki);
db_begin_transaction();
zDate = date_in_standard_format("now");
blob_appendf(&wiki, "D %s\n", zDate);
blob_appendf(&wiki, "L %F\n", zPageName);
if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")!=0 ){
blob_appendf(&wiki, "N %s\n", zMimetype);
}
if( rid ){
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
blob_appendf(&wiki, "P %s\n", zUuid);
free(zUuid);
}
if( !login_is_nobody() ){
blob_appendf(&wiki, "U %F\n", login_name());
}
appendRemark(&body, zMimetype);
blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body));
md5sum_blob(&wiki, &cksum);
blob_appendf(&wiki, "Z %b\n", &cksum);
blob_reset(&cksum);
wiki_put(&wiki, rid, wiki_need_moderation(0));
db_end_transaction(0);
manifest_destroy(pWiki);
cgi_redirectf("wiki?name=%T", zPageName);
return;
}
if( !isSandbox && P("cancel")!=0 ){
manifest_destroy(pWiki);
cgi_redirectf("wiki?name=%T", zPageName);
return;
}
style_set_current_page("%T?name=%T", g.zPath, zPageName);
style_set_current_feature("wiki");
style_header("Append Comment To: %s", zPageName);
if( !goodCaptcha ){
@ <p class="generalError">Error: Incorrect security code.</p>
}
if( isSandbox ){
@ <p class="generalError">Error: the Sandbox page may not
@ be appended to.</p>
}
if( !isSandbox && P("preview")!=0 ){
Blob preview;
blob_zero(&preview);
appendRemark(&preview, zMimetype);
@ Preview:<hr />
safe_html_context(DOCSRC_WIKI);
wiki_render_by_mimetype(&preview, zMimetype);
@ <hr />
|
| ︙ | ︙ | |||
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 |
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
@ <br />
@ <input type="submit" name="preview" value="Preview Your Comment" />
@ <input type="submit" name="submit" value="Append Your Changes" />
@ <input type="submit" name="cancel" value="Cancel" />
captcha_generate(0);
@ </form>
style_finish_page();
}
/*
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
| > | 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 |
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
@ <br />
@ <input type="submit" name="preview" value="Preview Your Comment" />
@ <input type="submit" name="submit" value="Append Your Changes" />
@ <input type="submit" name="cancel" value="Cancel" />
captcha_generate(0);
@ </form>
manifest_destroy(pWiki);
style_finish_page();
}
/*
** WEBPAGE: whistory
** URL: /whistory?name=PAGENAME
**
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
947 948 949 950 951 952 953 | ** ** Sets the start type of the service. TYPE can be "manual", ** which means you need to start the service yourself with the ** 'fossil winsrv start' command or with the "net start" command ** from the operating system. If TYPE is set to "auto", the service ** will be started automatically by the system during startup. ** | | | 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 | ** ** Sets the start type of the service. TYPE can be "manual", ** which means you need to start the service yourself with the ** 'fossil winsrv start' command or with the "net start" command ** from the operating system. If TYPE is set to "auto", the service ** will be started automatically by the system during startup. ** ** --username USERNAME ** ** Specifies the user account which will be used to run the ** service. The account needs the "Logon as a service" right ** enabled in its profile. Specify local accounts as follows: ** ".\\USERNAME". By default, the "LocalSystem" account will be ** used. ** |
| ︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 |
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zAltBase = find_option("baseurl", 0, 1);
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
| | | 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 |
SC_HANDLE hSvc;
SERVICE_DESCRIPTIONW
svcDescr = {L"Fossil - Distributed Software Configuration Management"};
DWORD dwStartType = SERVICE_DEMAND_START;
const char *zAltBase = find_option("baseurl", 0, 1);
const char *zDisplay = find_option("display", "D", 1);
const char *zStart = find_option("start", "S", 1);
const char *zUsername = find_option("username", 0, 1);
const char *zPassword = find_option("password", "W", 1);
const char *zPort = find_option("port", "P", 1);
const char *zNotFound = find_option("notfound", 0, 1);
const char *zFileGlob = find_option("files", 0, 1);
const char *zLocalAuth = find_option("localauth", 0, 0);
const char *zRepository = find_repository_option();
int useSCGI = find_option("scgi", 0, 0)!=0;
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 |
#define SYNC_UNVERSIONED 0x0100 /* Sync unversioned content */
#define SYNC_UV_REVERT 0x0200 /* Copy server unversioned to client */
#define SYNC_UV_TRACE 0x0400 /* Describe UV activities */
#define SYNC_UV_DRYRUN 0x0800 /* Do not actually exchange files */
#define SYNC_IFABLE 0x1000 /* Inability to sync is not fatal */
#define SYNC_CKIN_LOCK 0x2000 /* Lock the current check-in */
#define SYNC_NOHTTPCOMPRESS 0x4000 /* Do not compression HTTP messages */
#endif
/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
return x>0.0 ? x : -x;
| > | 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 |
#define SYNC_UNVERSIONED 0x0100 /* Sync unversioned content */
#define SYNC_UV_REVERT 0x0200 /* Copy server unversioned to client */
#define SYNC_UV_TRACE 0x0400 /* Describe UV activities */
#define SYNC_UV_DRYRUN 0x0800 /* Do not actually exchange files */
#define SYNC_IFABLE 0x1000 /* Inability to sync is not fatal */
#define SYNC_CKIN_LOCK 0x2000 /* Lock the current check-in */
#define SYNC_NOHTTPCOMPRESS 0x4000 /* Do not compression HTTP messages */
#define SYNC_ALLURL 0x8000 /* The --all flag - sync to all URLs */
#endif
/*
** Floating-point absolute value
*/
static double fossil_fabs(double x){
return x>0.0 ? x : -x;
|
| ︙ | ︙ |
Changes to www/bugtheory.wiki.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | to repopulate the table using the new column names. Note that the TICKET table schema and content is part of the local state of a repository and is not shared with other repositories during a sync, push, or pull. Each repository also defines scripts used to generate web pages for creating new tickets, viewing existing tickets, and modifying an existing ticket. These scripts consist of HTML with an embedded | | | < < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | to repopulate the table using the new column names. Note that the TICKET table schema and content is part of the local state of a repository and is not shared with other repositories during a sync, push, or pull. Each repository also defines scripts used to generate web pages for creating new tickets, viewing existing tickets, and modifying an existing ticket. These scripts consist of HTML with an embedded scripts written a Tcl-like language called "[./th1.md|TH1]". Every new fossil repository is created with default scripts. Administrators wishing to customize their ticket entry, viewing, and editing screens should modify the default scripts to suit their needs. These screen generator scripts are part of the local state of a repository and are not shared with other repositories during a sync, push, or pull. <i>To be continued...</i> |
Changes to www/changes.wiki.
1 2 | <title>Change Log</title> | > > > > > > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<title>Change Log</title>
<h2 id='v2_18'>Changes for version 2.18 (pending)</h2>
* [/help?cmd=/chat|The /chat page] input options have been reworked
again for better cross-browser portability.
* When sending a [/help?cmd=/chat|/chat] message fails, it is no longer
immediately lost and sending may optionally be retried.
<h2 id='v2_17'>Changes for version 2.17 (2021-10-09)</h2>
* Major improvements to the "diff" subsystem, including: <ul>
<li> Added new [/help?cmd=diff|formatting options]: --by, -b, --webpage, --json, --tcl.
<li> Partial-line matching for unified diffs
<li> Better partial-line matching for side-by-side diffs
<li> Buttons on web-based diffs to show more context
<li> Performance improvements
</ul>
|
| ︙ | ︙ |
Changes to www/chat.md.
| ︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | who performed the deletion, not the author of the deleted comment). That can potentially lead to odd corner cases where a user shows up in the list but has no messages which are currently visible because they were deleted, or an admin user who has not posted anything but deleted a message. That is a known minor cosmetic-only bug with a resolution of "will not fix." ## Implementation Details *You do not need to understand how Fossil chat works in order to use it. But many developers prefer to know how their tools work. This section is provided for the benefit of those curious developers.* The [/chat](/help?cmd=/chat) webpage downloads a small amount of HTML and a small amount of javascript to run the chat session. The javascript uses XMLHttpRequest (XHR) to download chat content, post new content, or delete historical messages. The following web interfaces are used by the XHR: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
who performed the deletion, not the author of the deleted
comment). That can potentially lead to odd corner cases where a user
shows up in the list but has no messages which are currently visible
because they were deleted, or an admin user who has not posted
anything but deleted a message. That is a known minor cosmetic-only
bug with a resolution of "will not fix."
### <a id="cli"></a> The `fossil chat` Command
Type [fossil chat](/help?cmd=chat) from within any open check-out
to bring up a chatroom for the project that is in that checkout.
The new chat window will attempt to connect to the default sync
target for that check-out (the server whose URL is shown by the
[fossil remote](/help?cmd=remote) command).
### <a id="robots"></a> Chat Messages From Robots
The [fossil chat send](/help?cmd=chat) can be used by project-specific
robots to send notifications to the chatroom. For example, on the
[SQLite project](https://sqlite.org/) (for which the Fossil chatroom
feature, and indeed all of Fossil, was invented) there are long-running
fuzz servers that sometimes run across obscure problems. Whenever this
happens, a message is sent to the SQLite developers chatroom altering
them to the problem.
The recommended way to allow robots to send chat messages is to create
a new user on the server for each robot. Give each such robot account
the "C" privilege only. That means that the robot user account will be
able to send chat messages, but not do anything else. Then, in the
program or script that runs the robot, when it wants to send a chat
message, have it run a command like this:
> ~~~~
fossil chat send --remote https://robot:PASSWORD@project.org/fossil \
--message 'MESSAGE TEXT' --file file-to-attach.txt
~~~~
Substitute the appropriate project URL, robot account
name and password, message text and file attachment, of course.
## Implementation Details
*You do not need to understand how Fossil chat works in order to use it.
But many developers prefer to know how their tools work.
This section is provided for the benefit of those curious developers.*
The [/chat](/help?cmd=/chat) webpage downloads a small amount of HTML
and a small amount of javascript to run the chat session. The
javascript uses XMLHttpRequest (XHR) to download chat content, post
new content, or delete historical messages. The following web
interfaces are used by the XHR:
* [/chat-poll](/help?name=/chat-poll) →
Downloads chat content as JSON.
Chat messages are numbered sequentially.
The client tells the server the largest chat message it currently
holds, and the server sends back subsequent messages. If there
are no subsequent messages, the /chat-poll page blocks until new
messages are available.
* [/chat-send](/help?name=/chat-send) →
Sends a new chat message to the server.
* [/chat-delete](/help?name=/chat-delete) →
Deletes a chat message.
Fossil chat uses the venerable "hanging GET" or
"[long polling](wikipedia:/wiki/Push_technology#Long_polling)"
technique to recieve asynchronous notification of new messages.
This is done because long polling works well with CGI and SCGI,
which are the usual mechanisms for setting up a Fossil server.
More advanced notification techniques such as
[Server-sent events](wikipedia:/wiki/Server-sent_events) and especially
[WebSockets](wikipedia:/wiki/WebSocket) might seem more appropriate for
a chat system, but those technologies are not compatible with CGI.
Downloading of posted files and images uses a separate, non-XHR interface:
* [/chat-download](/help?name=/chat-download) →
Fetches the file content associated with a post (one file per
post, maximum). In the UI, this is accessed via links to uploaded
files and via inlined image tags.
Chat messages are stored on the server-side in the CHAT table of
the repository.
> ~~~
CREATE TABLE repository.chat(
msgid INTEGER PRIMARY KEY AUTOINCREMENT,
mtime JULIANDAY, -- Time for this entry - Julianday Zulu
lmtime TEXT, -- Client YYYY-MM-DDZHH:MM:SS when message originally sent
xfrom TEXT, -- Login of the sender
xmsg TEXT, -- Raw, unformatted text of the message
fname TEXT, -- Filename of the uploaded file, or NULL
fmime TEXT, -- MIMEType of the upload file, or NULL
mdel INT, -- msgid of another message to delete
file BLOB -- Text of the uploaded file, or NULL
);
~~~
The CHAT table is not cross-linked with any other tables in the repository
schema. An administrator can "DROP TABLE chat;" at any time, without
harm (apart from deleting all chat history, of course). The CHAT table
is dropped when running [fossil scrub --verily](/help?cmd=scrub).
|
| ︙ | ︙ |
Changes to www/concepts.wiki.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | to setup and operate. This document is intended as a quick introduction to the concepts behind Fossil. See also: | | | | | | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
to setup and operate.
This document is intended as a quick introduction to the concepts
behind Fossil.
See also:
* [./glossary.md | Glossary]
* [./quickstart.wiki | Quick start guide]
<h2>2.0 Composition Of A Project</h2>
<verbatim type="pikchr float-right">
R1: cylinder "Remote" "Repository" fill 0xadd8e6 rad 70%
R2: cylinder same "Remote" "Repository" at 2.5*R1.wid right of R1
spline <-> from R1.e to 0.6<R1.se,R2.sw> then to 0.4<R1.ne,R2.nw> then to R2.w
text "HTTPS" at .5<R1.ne,R2.nw>
R3: cylinder same "Local" "Repository" fill 0x90ee90 \
at dist(R1.e,R2.w) below .5<R1,R2>
spline <-> from .5<R1.s,R1.se> to 0.6<R1.s,R3.w> to 0.5<R1.se,R3.n> to .5<R3.nw,R3.n> \
"HTTPS" above behind R1
spline <-> from R2.sw to .6<R2.sw,R3.n> to .5<R2.s,R3.e> to R3.ne "HTTPS" ljust
T1: line from 1.0cm heading 200 from R3.sw go 2.2cm heading 150 then 2.2cm west close \
fill 0xffff00 "Local" below "Source Tree" below
T2: line from 1.0cm heading 160 from R3.se same "Local" below "Source Tree" below
line <-> from R3.sw to T1.start
line <-> from R3.se to T2.start
</verbatim>
|
| ︙ | ︙ | |||
89 90 91 92 93 94 95 | remote repository into a local repository. Or one can do a "sync" which is a shortcut for doing both a push and a pull at the same time. Fossil also has the concept of "cloning". A "clone" is like a "pull", except that instead of beginning with an existing local repository, a clone begins with nothing and creates a new local repository that is a duplicate of a remote repository. | | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | remote repository into a local repository. Or one can do a "sync" which is a shortcut for doing both a push and a pull at the same time. Fossil also has the concept of "cloning". A "clone" is like a "pull", except that instead of beginning with an existing local repository, a clone begins with nothing and creates a new local repository that is a duplicate of a remote repository. Communication between repositories is normally via HTTPS. (SSH is also supported, as is unencrypted HTTP.) Remote repositories are identified by URL. You can also point a web browser at a repository and get human-readable status, history, and tracking information about the project. <h3 id="artifacts">2.1 Identification Of Artifacts</h3> A particular version of a particular file is called an "artifact". Each |
| ︙ | ︙ |
Changes to www/contribute.wiki.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<h2>2.0 Submitting Patches</h2>
Suggested changes or bug fixes can be submitted by creating a patch
against the current source tree:
<tt>fossil diff -i > my-change.patch</tt>
Post patches to
[https://fossil-scm.org/forum | the forum] or email them to
<a href="mailto:drh@sqlite.org">drh@sqlite.org</a>. Be sure to
describe in detail what the patch does and which version of Fossil
it is written against. It's best to make patches against tip-of-trunk
rather than against past releases.
| > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<h2>2.0 Submitting Patches</h2>
Suggested changes or bug fixes can be submitted by creating a patch
against the current source tree:
<tt>fossil diff -i > my-change.patch</tt>
Alternatively, you can create a binary patch:
<tt>fossil patch create my-change.db</tt>
Post patches to
[https://fossil-scm.org/forum | the forum] or email them to
<a href="mailto:drh@sqlite.org">drh@sqlite.org</a>. Be sure to
describe in detail what the patch does and which version of Fossil
it is written against. It's best to make patches against tip-of-trunk
rather than against past releases.
|
| ︙ | ︙ |
Changes to www/gitusers.md.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | We think this is a more sensible command design than `git pull` vs `git checkout`. ([…vs `git checkout` vs `git checkout`!][gcokoan]) [fpull]: /help?cmd=pull [gpull]: https://git-scm.com/docs/git-pull [gcokoan]: https://stevelosh.com/blog/2013/04/git-koans/#s2-one-thing-well | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | We think this is a more sensible command design than `git pull` vs `git checkout`. ([…vs `git checkout` vs `git checkout`!][gcokoan]) [fpull]: /help?cmd=pull [gpull]: https://git-scm.com/docs/git-pull [gcokoan]: https://stevelosh.com/blog/2013/04/git-koans/#s2-one-thing-well #### <a id="close" name="dotfile"></a> Closing a Check-Out The [`fossil close`][close] command dissociates a check-out directory from the Fossil repository database, nondestructively inverting [`fossil open`][open]. (Contrast [its closest inverse](#worktree), `git worktree remove`, which *is* destructive in Git!) This Fossil command does not |
| ︙ | ︙ | |||
322 323 324 325 326 327 328 | you’re following [the directory scheme exemplified above](#rname). That said, it does emphasize an earlier point: Fossil doesn’t care where you put the repo DB file or what you name it. [clone]: /help?cmd=clone [close]: /help?cmd=close | | | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | you’re following [the directory scheme exemplified above](#rname). That said, it does emphasize an earlier point: Fossil doesn’t care where you put the repo DB file or what you name it. [clone]: /help?cmd=clone [close]: /help?cmd=close [gloss]: ./glossary.md [open]: /help?cmd=open [set]: /help?cmd=setting [server]: /help?cmd=server [stash]: /help?cmd=stash [undo]: /help?cmd=undo |
| ︙ | ︙ | |||
484 485 486 487 488 489 490 | in Fossil, because the indexes always let us find our way back into the hash tree. ## <a id="slcom"></a> Summary Line Convention In Commit Comments The Git convention of a [length-limited summary line][lsl] at the start | | | < < | > | > > | < > | < > > > | < | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | in Fossil, because the indexes always let us find our way back into the hash tree. ## <a id="slcom"></a> Summary Line Convention In Commit Comments The Git convention of a [length-limited summary line][lsl] at the start of commit comments is not enforced or obeyed by default in Fossil. However, there is a setting under Admin → Timeline → “Truncate comment at first blank line (Git-style)” to change this for `/timeline` displays. Alternately, you could enable the “Allow block-markup in timeline” setting under Admin → Timeline, then apply [local skin customizations][cskin] to put that first comment in in bold or whatever suits. Because this isn’t a typical Fossil convention, you’re likely to find other odd differences between it and Git-based infrastructure. For instance, Vim doesn’t ship with syntax support for Fossil commit messages if you set `EDITOR=vim` in your shell environment, so you won’t get over-limit highlighting for first-line text beyond the 50th character and such, because it doesn’t recognize Fossil commit messages and apply similar rules as to Git commit messages. [cskin]: ./customskin.md [lsl]: https://chris.beams.io/posts/git-commit/#limit-50 <a id="staging"></a> |
| ︙ | ︙ |
Added www/glossary.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# Glossary
There are several terms-of-art in Fossil that have specific meanings
which are either not immediately obvious to an outsider or which have
technical associations that can lead someone to either use the terms
incorrectly or to get the wrong idea from someone using those terms
correctly. We hope to teach users how to properly “speak Fossil” with
this glossary.
Each definition is followed by a bullet-point list of clarifying
details. These are not part of the definition itself.
## <a id="project"></a>Project
A collection of one or more computer files that serve some conceptually
unified purpose, which purpose changes and evolves over time, with the
history of that project being a valuable record.
* We qualify the Fossil definition of this common word like this to
set aside cases where a zip file or tarball would suffice. If you
can pack your project up into such an archive once and be done with
it, Fossil is overkill.
And yet that is often just the beginning, since there is often a
need for something to be changed, so now you have “version 2” of the
archive file. If you can foresee yourself creating versioned archive
files for your project, then you probably should be using Fossil for
it instead, then using Fossil’s [zip] or [tarball] command to
automatically produce archives of the latest version rather than
manually produce and track versions of the archive. The web version
of these commands ([`/zip`][zw] and [`/tarball`][tw]) are
particularly useful for public distribution of the latest version of
a project’s files.
* Fossil was designed to host the SQLite software project, which is
comprised of source code, makefiles, scripts, documentation files,
and so forth. Fossil is also useful for many other purposes, such as
a fiction book project where each chapter is held in a separate file
and assembled into a finished whole deliverable.
* We speak of projects being more than one file because even though
Fossil can be made to track the history of a single file, it is far
more often the case that when you get to something of a scale
sufficient to be called a “project,” there is more than one
version-tracked file involved, if not at the start, then certainly
by the end of the project.
We used the example of a fiction book above, with one chapter per
file. That implies scripts for combining those chapters into the
finished book and converting that into PDF and ePub outputs, each of
which benefit from being version-tracked.
You could instead use a Word DOCX file for the entire book project,
with these implicit scripts replaced by Word menu commands. Fossil
will happily track that single file’s evolution for you, though
there are [good reasons](./image-format-vs-repo-size.md) to *not* do
that.
Let us say you choose to solve the primary problems brought up in
that document by using a format like AsciiDoc instead. You could
still use a single file for the entire book’s prose content, but
even then you’re still likely to want separate files for a style
sheet, a script to convert the HTML to PDF and ePub in a reliably
repeatable fashion, cover artwork files, instructions to the
printing house, and so forth.
* Fossil requires that all the files for a project be collected into a
single directory hierarchy, owned by a single user with full rights
to modify those files. Fossil is not a good choice for managing a
project that has files scattered hither and yon all over the file
system, nor of collections of files with complicated ownership and
access rights.
A good mental model for a Fossil project is a versioned zip file or
tarball. If you cannot easily conceive of creating or extracting
such an archive for your project, Fossil is probably not a good fit.
As a counterexample, a project made of an operating system
installation’s configuration file set is not a good use of Fossil,
because you’ll have all of your OS’s *other* files intermixed.
Worse, Fossil doesn’t track OS permissions, so even if you were to
try to use Fossil as a system deployment tool by archiving versions
of the OS configuration files and then unpacking them on a new
system, the extracted project files would have read/write access by
the user who did the extraction, which probably isn’t want you were
wanting.
And as a counter-counterexample, a project made of your user’s [Vim]
configuration is a much better use of Fossil, because it’s all held
within `~/.vim`, and your user has full rights to that subdirectory.
[tarball]: /help?cmd=tarball
[tw]: /help?cmd=/tarball
[Vim]: https://www.vim.org/
[zip]: /help?cmd=zip
[zw]: /help?cmd=/zip
## Repository <a id="repository" name="repo"></a>
A single file that contains all historical versions of all files in a
project, which can be [cloned] to other machines and
[synchronized][sync] with them. Jargon: repo.
* A Fossil repo is similar to a zip archive in that it is a single
file that stores compressed versions of one or more files. Files can be
extracted from the repo, and new files can be added to the repo,
just as with a zip archive, but a Fossil repo has other capabilities
above and beyond what simple archive formats can do.
* Fossil does not care what you name your repository files, though
we do suggest appending “`.fossil` as a standard extension. There is
only one place in Fossil where that’s required, being the “directory
name” form of [the `fossil server DIRECTORY` command][svrcmd].
* Cloned and synced repos redundantly store all available information
about that project, so if any one repo is lost, all of the cloned
historical content of the project as of the last sync is preserved
in each surviving repo.
Each user generally clones the project repository down to each
computer they use to participate in that project, and there is
usually at least one central host for the project as well, so there
is usually plenty of redundancy in any given Fossil-based project.
That said, a Fossil repository clone is a backup only in a limited
sense, because some information can’t be cloned, some doesn’t sync
by default, and some data is neither clonable nor syncable. We cover
these limitations and the workarounds for them in a separate
document, [Backing Up a Remote Fossil Repository][backup].
* Rather than be a backup, a Fossil repository clone is a
communication method for coordinating work on the project among
multiple machines and users: local work done against one repository
is communicated up to its parent repository on the next sync, and
work done on other repositories that were previously synced up to
that parent get pulled down into the local repo clone.
This bidirectional sync is automatic and on by default in Fossil.
You can [disable it][asdis], or you can [push] or [pull]
unidirectionally, if you wish.
The Fossil philosophy is that all project information resides in
each clone of the repository. In the ideal world, this would occur
instantly and automatically, but in actual use, Fossil falls
somewhat short of that mark. Some limitations are simply
technological: a given clone may be temporarily out of communication
with its parent repository, network delays exist, and so forth.
Fossil is [an AP mode system][CAP]. (This is sometimes called
“eventual consistency.”) Other cases come down to administrative
necessity, as covered in [the backup doc][backup].
* Fossil doesn’t require that you have redundant clones. Whether you
do or not is a local decision based on usage needs, communication
requirements, desire for backups, and so forth.
* Fossil doesn’t care where the repositories are stored, but we
recommend keeping them all in a single subdirectory such as
"`~/fossils`" or "`%USERPROFILE%\Fossils`". A flat set of files
suffices for simple purposes, but you may have use for something
more complicated. This author uses a scheme like the following on
mobile machines that shuttle between home and the office:
``` pikchr toggle indent
scale=0.8
box "~/museum/" fit
move right 0.1
line right dotted
move right 0.05
box invis "where one stores valuable fossils" ljust
arrow down 50% from first box.s then right 50%
box "work/" fit
move right 0.1
line dotted
move right 0.05
box invis "projects from $DAYJOB" ljust
arrow down 50% from 2nd vertex of previous arrow then right 50%
box "home/" fit
move right 0.1
line dotted right until even with previous line.end
move right 0.05
box invis "personal at-home projects" ljust
arrow down 50% from 2nd vertex of previous arrow then right 50%
box "other/" fit
move right 0.1
line dotted right until even with previous line.end
move right 0.05
box invis "clones of Fossil itself, SQLite, etc." ljust
```
[asdis]: /help?cmd=autosync
[backup]: ./backup.md
[CAP]: ./cap-theorem.md
[cloned]: /help?cmd=clone
[pull]: /help?cmd=pull
[push]: /help?cmd=push
[svrcmd]: /help?cmd=server
[sync]: /help?cmd=sync
## Check-in <a id="check-in" name="ci"></a>
A version of the project’s files that have been committed to the
repository. It is a snapshot of the project at an instant in time, as
seen from a single [check-out’s](#co) perspective. Synonyms: version,
snapshot, revision, commit. Sometimes styled “`CHECKIN`”, especially in
command documentation where any [valid checkin name][ciname] can be
used.
* The long list of synonyms is confusing to new Fossil users,
particularly the noun sense of the word “commit,” but it’s easy
enough to internalize the concepts. [Committing][commit] creates a
*commit.* It may also be said to create a checked-in *version* of a
particular *revision* of the project’s files, thus creating an
immutable *snapshot* of the project’s state at the time of the
commit. Fossil users find each of these different words for the
same concept useful for expressive purposes among ourselves, but to
Fossil proper, they all mean the same thing.
You will find all of these synonyms used in the Fossil documentation.
Some day we may settle on a single term, but it doesn’t seem likely.
* Check-ins are immutable.
* Check-ins exist only inside the repository. Contrast a
[check-out](#co).
* Check-ins may have [one or more names][ciname], but only the SHA
hash is globally unique, across all time; we call it the check-in’s
canonical name. The other names are either imprecise, contextual, or
change their meaning over time and across [repositories](#repo).
[ciname]: ./checkin_names.wiki
## Check-out <a id="check-out" name="co"></a>
A set of files extracted from a [repository](#repo) that represent a
particular [check-in](#ci) of the [project](#project).
* Unlike a check-in, a check-out is mutable. It may start out as a
version of a particular check-in extracted from the repository, but
the user is then free to make modifications to the checked-out
files. Once those changes are formally [committed][commit], they
become a new immutable check-in, derived from its parent check-in.
* You can switch from one check-in to another within a check-out
directory by passing those names to [the `fossil update`
command][update].
* Check-outs relate to repositories in a one-to-many fashion: it is
common to have a single repo clone on a machine but to have it
[open] in [multiple working directories][mwd]. Check-out directories
are associated with the repos they were created from by settings
stored in the check-out drectory. This is in the `.fslckout` file on
POSIX type systems, but for historical compatibility reasons, it’s
called `_FOSSIL_` by native Windows builds of Fossil.
(Contrast the Cygwin and WSL Fossil binaries, which use POSIX file
naming rules.)
* In the same way that one cannot extract files from a zip archive
without having a copy of that zip file, one cannot make check-outs
without access to the repository file or a clone thereof.
* Because a Fossil repository is a SQLite database file, the same
rules for avoiding data corruption apply to it. In particular, it is
[nearly a hard requirement][h2cflp] that the repository clone be on
the same machine as the one where you make check-outs and the
subsequent check-ins.
That said, the relative locations of the repo and the check-out
within the local file system are arbitrary. The repository may be
located inside the folder holding the check-out, but it certainly
does not have to be, and it usually is not. As an example, [the
Fossil plugin for Visual Studio Code][fpvsc] defaults to storing the
repo clone within the project directory as a file called `.fsl`, but
this is because VSCode’s version control features assume it’s being
used with Git, where the repository is the `.git` subdirectory
contents. With Fossil, [different check-out workflows][cwork] are
preferred.
[commit]: /help?cmd=commit
[cwork]: ./ckout-workflows.md
[h2cflp]: https://www.sqlite.org/howtocorrupt.html#_file_locking_problems
[fpvsc]: https://marketplace.visualstudio.com/items?itemName=koog1000.fossil
[open]: /help?cmd=open
[mwd]: ./ckout-workflows.md#mcw
[update]: /help?cmd=update
<div style="height:50em" id="this-space-intentionally-left-blank"></div>
|
Changes to www/index.wiki.
| ︙ | ︙ | |||
81 82 83 84 85 86 87 |
atomic even if interrupted by a power loss or system crash.
Automatic [./selfcheck.wiki | self-checks] verify that all aspects of
the repository are consistent prior to each commit.
8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license].
<hr>
| | | | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
atomic even if interrupted by a power loss or system crash.
Automatic [./selfcheck.wiki | self-checks] verify that all aspects of
the repository are consistent prior to each commit.
8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license].
<hr>
<h3>Latest Release: 2.17 ([/timeline?c=version-2.17|2021-10-09])</h3>
* [/uv/download.html|Download]
* [./changes.wiki#v2_17|Change Summary]
* [/timeline?p=version-2.17&bt=version-2.16&y=ci|Check-ins in version 2.17]
* [/timeline?df=version-2.17&y=ci|Check-ins derived from the 2.17 release]
* [/timeline?t=release|Timeline of all past releases]
<hr>
<h3>Quick Start</h3>
1. [/uv/download.html|Download] or install using a package manager or
[./build.wiki|compile from sources].
|
| ︙ | ︙ |
Changes to www/interwiki.md.
| ︙ | ︙ | |||
109 110 111 112 113 114 115 | The intermap is stored in the CONFIG table of the repository database, in entries with names of the form "<tt>interwiki:</tt><i>Tag</i>". The value for each such entry is a JSON string that defines the base URL and extensions for Hash and Wiki links. ## See Also | < | | | 109 110 111 112 113 114 115 116 117 | The intermap is stored in the CONFIG table of the repository database, in entries with names of the form "<tt>interwiki:</tt><i>Tag</i>". The value for each such entry is a JSON string that defines the base URL and extensions for Hash and Wiki links. ## See Also 1. [](https://www.mediawiki.org/wiki/Manual:Interwiki) 2. [](https://duckduckgo.com/?q=interwiki+links&ia=web) |
Changes to www/mkindex.tcl.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 67 |
fiveminutes.wiki {Up and Running in 5 Minutes as a Single User}
forum.wiki {Fossil Forums}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-is-not-relational.md {Introduction to the (Non-relational) Fossil Data Model}
fossil_prompt.wiki {Fossilized Bash Prompt}
fossil-v-git.wiki {Fossil Versus Git}
globs.md {File Name Glob Patterns}
| > | | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
fiveminutes.wiki {Up and Running in 5 Minutes as a Single User}
forum.wiki {Fossil Forums}
foss-cklist.wiki {Checklist For Successful Open-Source Projects}
fossil-from-msvc.wiki {Integrating Fossil in the Microsoft Express 2010 IDE}
fossil-is-not-relational.md {Introduction to the (Non-relational) Fossil Data Model}
fossil_prompt.wiki {Fossilized Bash Prompt}
fossil-v-git.wiki {Fossil Versus Git}
gitusers.md {Git to Fossil Translation Guide}
globs.md {File Name Glob Patterns}
glossary.md {Glossary}
grep.md {Fossil grep vs POSIX grep}
hacker-howto.wiki {Hacker How-To}
hacker-howto.wiki {Fossil Developers Guide}
hashes.md {Hashes: Fossil Artifact Identification}
hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
/help {Lists of Commands and Webpages}
hints.wiki {Fossil Tips And Usage Hints}
|
| ︙ | ︙ |
Changes to www/newrepo.wiki.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | a branch or experimental code. Making your repository available over the web is trivial to do. We assume you have some web space where you can store your fossil file and run a CGI script. If not, then this option is not for you. If you do, then here's how... | | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | a branch or experimental code. Making your repository available over the web is trivial to do. We assume you have some web space where you can store your fossil file and run a CGI script. If not, then this option is not for you. If you do, then here's how... Copy the fossil repository file to your web server (it doesn't matter where, really). In your <tt>cgi-bin</tt> (or equivalent) directory, create a file which looks like this: <verbatim> #!/path/to/fossil |
| ︙ | ︙ |
Changes to www/password.wiki.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | Fossil self-hosting repository. Then the value of USER.PW for alice would be the SHA1 hash of <blockquote> CE59BB9F186226D80E49D1FA2DB29F935CCA0333/alice/asdfg </blockquote> | < | | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | Fossil self-hosting repository. Then the value of USER.PW for alice would be the SHA1 hash of <blockquote> CE59BB9F186226D80E49D1FA2DB29F935CCA0333/alice/asdfg </blockquote> Note that by including the project-code and the login as part of the hash, a different USER.PW value results even if two or more users on the repository select the same "asdfg" password or if user alice reuses the same password on multiple projects. Whenever a password is changed using the web interface or using the "user" command-line method, the new password is stored using the SHA1 encoding. Thus, cleartext passwords will gradually migrate to become SHA1 passwords. All remaining cleartext passwords can be converted to SHA1 passwords using the following command: |
| ︙ | ︙ | |||
75 76 77 78 79 80 81 | address of the client is stored in the USER.COOKIE and USER.IPADDR fields of the USER table on the server. The USER.CEXPIRE field holds an expiration date for the cookie, encoded as a Julian day number. On all subsequent HTTP requests, the cookie value is matched against the USER table to enable access to the repository. | < < < < < < < < < < < < < < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | address of the client is stored in the USER.COOKIE and USER.IPADDR fields of the USER table on the server. The USER.CEXPIRE field holds an expiration date for the cookie, encoded as a Julian day number. On all subsequent HTTP requests, the cookie value is matched against the USER table to enable access to the repository. Note that in order to log into a Fossil server, it is necessary to write information into the repository database. Hence, login is not possible on a Fossil repository with a read-only database file. The user password is sent over the wire as cleartext on the initial login attempt. The plan moving forward is to compute the SHA1 hash of the password on the client using JavaScript and then send only the hash |
| ︙ | ︙ |
Changes to www/permutedindex.html.
| ︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> <li><a href="settings.wiki">Fossil Settings</a></li> <li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> <li><a href="fossil_prompt.wiki">Fossilized Bash Prompt</a></li> <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="gitusers.md">Git to Fossil Translation Guide</a></li> <li><a href="hacker-howto.wiki">Hacker How-To</a></li> <li><a href="adding_code.wiki">Hacking Fossil</a></li> <li><a href="hashpolicy.wiki">Hash Policy: Choosing Between SHA1 and SHA3-256</a></li> <li><a href="hashes.md">Hashes: Fossil Artifact Identification</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> <li><a href="aboutdownload.wiki">How The Download Page Works</a></li> | > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> <li><a href="settings.wiki">Fossil Settings</a></li> <li><a href="hints.wiki">Fossil Tips And Usage Hints</a></li> <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> <li><a href="fossil_prompt.wiki">Fossilized Bash Prompt</a></li> <li><a href="faq.wiki">Frequently Asked Questions</a></li> <li><a href="gitusers.md">Git to Fossil Translation Guide</a></li> <li><a href="glossary.md">Glossary</a></li> <li><a href="hacker-howto.wiki">Hacker How-To</a></li> <li><a href="adding_code.wiki">Hacking Fossil</a></li> <li><a href="hashpolicy.wiki">Hash Policy: Choosing Between SHA1 and SHA3-256</a></li> <li><a href="hashes.md">Hashes: Fossil Artifact Identification</a></li> <li><a href="index.wiki">Home Page</a></li> <li><a href="aboutcgi.wiki">How CGI Works In Fossil</a></li> <li><a href="aboutdownload.wiki">How The Download Page Works</a></li> |
| ︙ | ︙ |
Changes to www/quickstart.wiki.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 | </blockquote> <h2 id="workflow" name="fslclone">General Work Flow</h2> <p>Fossil works with repository files (a database in a single file with the project's complete history) and with checked-out local trees (the working directory you use to do your work). | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
</blockquote>
<h2 id="workflow" name="fslclone">General Work Flow</h2>
<p>Fossil works with repository files (a database in a single file with the project's
complete history) and with checked-out local trees (the working directory
you use to do your work).
(See [./glossary.md | the glossary] for more background.)
The workflow looks like this:</p>
<ul>
<li>Create or clone a repository file. ([/help/init|fossil init] or
[/help/clone | fossil clone])
<li>Check out a local tree. ([/help/open | fossil open])
<li>Perform operations on the repository (including repository
|
| ︙ | ︙ |
Changes to www/server/any/cgi.md.
| ︙ | ︙ | |||
66 67 68 69 70 71 72 73 | Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b> will serve up the repository `/home/fossil/repos/XYZ.fossil` if it exists. Additional options available to the CGI script are [documented separately](../../cgi.wiki). *[Return to the top-level Fossil server article.](../)* | > > > > > > > > > > > > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository `/home/fossil/repos/XYZ.fossil` if it
exists.
Additional options available to the CGI script are [documented
separately](../../cgi.wiki).
#### CGI with Apache behind an Nginx proxy
For the case where the Fossil repositories live on a computer, itself behind
an Internet-facing machine that employs Nginx to reverse proxy HTTP(S) requests
and take care of the TLS part of the connections in a transparent manner for
the downstream web servers, the CGI parameter `HTTPS=on` might not be set.
However, Fossil in CGI mode needs it in order to generate the correct links.
Apache can be instructed to pass this parameter further to the CGI scripts for
TLS connections with a stanza like
SetEnvIf X-Forwarded-Proto "https" HTTPS=on
in its config file section for CGI, provided that
proxy_set_header X-Forwarded-Proto $scheme;
has been be added in the relevant proxying section of the Nginx config file.
*[Return to the top-level Fossil server article.](../)*
|
Changes to www/sync.wiki.
| ︙ | ︙ | |||
702 703 704 705 706 707 708 | the client because the client login lacks the "write-unversioned" permission.</p> <li><p><b>uv-push-ok</b></i> <p>A server sends the uv-push-ok pragma to the client in response to a uv-hash pragma with a mismatched content hash argument. This pragma indicates that there are differences in unversioned content | | | | 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | the client because the client login lacks the "write-unversioned" permission.</p> <li><p><b>uv-push-ok</b></i> <p>A server sends the uv-push-ok pragma to the client in response to a uv-hash pragma with a mismatched content hash argument. This pragma indicates that there are differences in unversioned content between the client and server and that content can be transferred in either direction. The server is willing to accept content from the client because the client login has the "write-unversioned" permission.</p> <li><p><b>ci-lock</b> <i>CHECKIN-HASH CLIENT-ID</i></p> <p>A client sends the "ci-lock" pragma to the server to indicate that it is about to add a new check-in as a child of the CHECKIN-HASH check-in and on the same branch as CHECKIN-HASH. If some other client has already indicated that it was also trying to commit against CHECKIN-HASH, that indicates that a fork is about to occur, and the server will reply with a "ci-lock-fail" pragma (see below). Check-in locks automatically expire when the check-in actually occurs, or after a timeout (currently one minute but subject to change). <li><p><b>ci-lock-fail</b> <i>LOGIN MTIME</i></p> <p>When a server receives two or more "ci-lock" pragma messages for the same check-in but from different clients, the second a subsequent ci-lock will provoke a ci-lock-fail pragma in the reply to let the client know that it if continues with the check-in it will likely generate a fork. The LOGIN and MTIME |
| ︙ | ︙ |
Changes to www/userlinks.wiki.
1 2 3 4 5 6 7 |
<title>Links For Fossil Users:</title>
* [./permutedindex.html | Documentation index] with [/search?c=d | full text search].
* [./reviews.wiki | Testimonials] from satisfied Fossil users and
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
* [./faq.wiki | Frequently Asked Questions]
* The [./concepts.wiki | concepts] behind Fossil.
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<title>Links For Fossil Users:</title>
* [./permutedindex.html | Documentation index] with [/search?c=d | full text search].
* [./reviews.wiki | Testimonials] from satisfied Fossil users and
[./quotes.wiki | Quotes] about Fossil and other DVCSes.
* [./faq.wiki | Frequently Asked Questions]
* The [./concepts.wiki | concepts] behind Fossil.
[./glossary.md | Another viewpoint].
* [./quickstart.wiki | Quick Start] guide to using Fossil.
* [./qandc.wiki | Questions & Criticisms] directed at Fossil.
* [./build.wiki | Compiling and Installing]
* Fossil supports [./embeddeddoc.wiki | embedded documentation]
that is versioned along with project source code.
* Fossil uses an [./fileformat.wiki | enduring file format] that is
designed to be readable, searchable, and extensible by people
|
| ︙ | ︙ |
Changes to www/whyusefossil.wiki.
| ︙ | ︙ | |||
37 38 39 40 41 42 43 |
<li>Avoid wasting time doing manual file copying
<li>Avoid human errors during manual backups
</ol>
</ol>
<p id="definitions"><b>II. Definitions</b></p>
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<li>Avoid wasting time doing manual file copying
<li>Avoid human errors during manual backups
</ol>
</ol>
<p id="definitions"><b>II. Definitions</b></p>
Moved to [./glossary.md | a separate document].
<p><b>III. Basic Fossil commands</b>
<ul>
<li><p><b>clone</b> →
Make a copy of a repository. The original repository
is usually (but not always) on a remote machine and the copy is on
|
| ︙ | ︙ |