Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge from trunk |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | rptview-submenu-paralink |
| Files: | files | file ages | folders |
| SHA3-256: |
9712d59d9ee76e381cc8810e2a62fc7a |
| User & Date: | george 2021-06-08 01:04:23.335 |
Context
|
2021-06-12
| ||
| 17:28 | Add a note to the Changelog. No code changes. ... (check-in: 528d628947 user: george tags: rptview-submenu-paralink) | |
|
2021-06-08
| ||
| 01:04 | Merge from trunk ... (check-in: 9712d59d9e user: george tags: rptview-submenu-paralink) | |
|
2021-06-07
| ||
| 17:48 | Include the login-group in the repository list of "fossil all ui". ... (check-in: fe178faa44 user: drh tags: trunk) | |
|
2021-05-25
| ||
| 16:14 | Split recognizable names of query parameters into three groups: 1) "...smplX" for the common use within user content 2) "...smplXa" that is provisioned to be used in aliases; 3) "...smplXs" that is provisioned to be used in custom skins. In all three groups X is a digit from {1,2,3,4,5}. ... (check-in: 588b376560 user: george tags: rptview-submenu-paralink) | |
Changes
Changes to skins/ardoise/css.txt.
| ︙ | ︙ | |||
957 958 959 960 961 962 963 |
background: #442800
}
span.timelineSelected {
border-radius: 5px;
border: solid #ff8000;
vertical-align: top;
text-align: left;
| | | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
background: #442800
}
span.timelineSelected {
border-radius: 5px;
border: solid #ff8000;
vertical-align: top;
text-align: left;
background-color: #442800;
}
.timelineSelected {
box-shadow: none;
}
.timelineSecondary {}
.timelineSecondary > .timelineColumnarCell,
.timelineSecondary > .timelineCompactCell,
|
| ︙ | ︙ | |||
1408 1409 1410 1411 1412 1413 1414 1415 |
background-color: #222;
}
.capsumRead {
background-color: #262;
}
.capsumWrite {
background-color: #662;
}
| > > > > | 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 |
background-color: #222;
}
.capsumRead {
background-color: #262;
}
.capsumWrite {
background-color: #662;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
body.branch .brlist > table > tbody > tr.selected {
background-color: #442800;
}
|
Changes to skins/bootstrap/css.txt.
cannot compute difference between binary files
Changes to skins/bootstrap/footer.txt.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<th1>
if {! $is_index && ! $is_home} {
html "</div>"
}
</th1>
</div>
<div id="push"></div>
</div>
<footer id="footer">
<p>© Copyright $<project_name>. All right reserved. Fossil $release_version · <a href="$home/timeline.rss">RSS</a></p>
</footer>
<script nonce="$<nonce>">
var tables = document.querySelectorAll('table');
| > > | | | > > | | | | | 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 |
<th1>
if {! $is_index && ! $is_home} {
html "</div>"
}
</th1>
</div>
<div id="push"></div>
</div>
<footer id="footer">
<p>© Copyright $<project_name>. All right reserved. Fossil $release_version · <a href="$home/timeline.rss">RSS</a></p>
</footer>
<script nonce="$<nonce>">
window.addEventListener( 'load', function() {
var i;
var tables = document.querySelectorAll('table');
for(i = 0; i < tables.length; i++) {
if (tables[i].id !== "timelineTable"){
tables[i].classList.add('table');
}
};
var submenus = document.querySelectorAll('.submenu');
var labels, j;
for (i = 0; i < submenus.length; i++) {
submenus[i].classList.add('btn-group');
labels = submenus[i].querySelectorAll('.label');
for (j = 0; j < labels.length; j++) {
labels[j].classList.remove('label');
labels[j].classList.add('btn');
labels[j].classList.add('btn-default');
labels[j].classList.add('btn-sm');
}
};
//Handle the collapsible navbar
var collapse = document.querySelector('[data-toggle="collapse"]');
collapse.onclick = function(){
var target = document.querySelector(
collapse.getAttribute('data-target')
);
target.classList.toggle('collapse');
target.classList.toggle('collapsed');
};
});</script>
|
Changes to skins/darkmode/css.txt.
| ︙ | ︙ | |||
546 547 548 549 550 551 552 |
border: 1px inset;
padding: 0 0.5em;
}
pre.udiff {
overflow-x: auto;
}
| > > > > > > > > > > | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
border: 1px inset;
padding: 0 0.5em;
}
pre.udiff {
overflow-x: auto;
}
body.report table.report tr td { color: black }
body.report table.report a { color: blue }
body.tkt td.tktDspValue { color: black }
body.tkt td.tktDspValue a { color: blue }
body.branch .brlist > table > tbody > tr:hover:not(.selected),
body.branch .brlist > table > tbody > tr.selected {
background-color: #442800;
}
|
Changes to skins/eagle/css.txt.
| ︙ | ︙ | |||
431 432 433 434 435 436 437 |
}
.capsumRead {
background-color: #006d00;
}
.capsumWrite {
background-color: #e5e500;
}
| > > > > > | 431 432 433 434 435 436 437 438 439 440 441 442 |
}
.capsumRead {
background-color: #006d00;
}
.capsumWrite {
background-color: #e5e500;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
body.branch .brlist > table > tbody > tr.selected {
background-color: #7EA2D9;
}
|
Changes to skins/xekri/css.txt.
| ︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 |
padding: 0 0.5em;
border-radius: 0.25em;
}
.debug {
color: black;
}
| > > > > > | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 |
padding: 0 0.5em;
border-radius: 0.25em;
}
.debug {
color: black;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
body.branch .brlist > table > tbody > tr.selected {
background-color: #444;
}
|
Changes to src/add.c.
| ︙ | ︙ | |||
437 438 439 440 441 442 443 |
char *zName;
int isDir;
Blob fullName = empty_blob;
/* file_tree_name() throws a fatal error if g.argv[i] is outside of the
** checkout. */
file_tree_name(g.argv[i], &fullName, 0, 1);
| < < < < < < < < < < < | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
char *zName;
int isDir;
Blob fullName = empty_blob;
/* file_tree_name() throws a fatal error if g.argv[i] is outside of the
** checkout. */
file_tree_name(g.argv[i], &fullName, 0, 1);
blob_reset(&fullName);
file_canonical_name(g.argv[i], &fullName, 0);
zName = blob_str(&fullName);
isDir = file_isdir(zName, RepoFILE);
if( isDir==1 ){
vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
}else if( isDir==0 ){
|
| ︙ | ︙ | |||
484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
);
}
blob_reset(&fullName);
}
glob_free(pIgnore);
glob_free(pClean);
add_files_in_sfile(vid);
db_end_transaction(0);
}
/*
** This function adds a file to list of files to delete from disk after
** the other actions required for the parent operation have completed
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 |
);
}
blob_reset(&fullName);
}
glob_free(pIgnore);
glob_free(pClean);
/** Check for Windows-reserved names and warn or exit, as
** appopriate. Note that the 'add' internal machinery already
** _silently_ skips over any names for which
** file_is_reserved_name() returns true or which is in the
** fossil_reserved_name() list. We do not need to warn for those,
** as they're outright verboten. */
if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
Stmt q = empty_Stmt;
db_prepare(&q,"SELECT pathname FROM sfile "
"WHERE win_reserved(pathname)");
int reservedCount = 0;
while( db_step(&q)==SQLITE_ROW ){
const char * zName = db_column_text(&q, 0);
++reservedCount;
if(allowReservedFlag){
fossil_warning("WARNING: Windows-reserved "
"filename: %s", zName);
}else{
fossil_warning("ERROR: Windows-reserved filename: %s", zName);
}
}
db_finalize(&q);
if(allowReservedFlag==0){
fossil_fatal("ERROR: %d Windows-reserved filename(s) added. "
"Use --allow-reserved to permit such names.",
reservedCount);
}
}
add_files_in_sfile(vid);
db_end_transaction(0);
}
/*
** This function adds a file to list of files to delete from disk after
** the other actions required for the parent operation have completed
|
| ︙ | ︙ |
Changes to src/alerts.c.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Logic for email notification, also known as "alerts" or "subscriptions". ** ** Are you looking for the code that reads and writes the internet ** email protocol? That is not here. See the "smtp.c" file instead. ** Yes, the choice of source code filenames is not the greatest, but ** it is not so bad that changing them seems justified. */ #include "config.h" |
| ︙ | ︙ | |||
62 63 64 65 66 67 68 | @ suname TEXT, -- corresponding USER entry @ sverified BOOLEAN DEFAULT true, -- email address verified @ sdonotcall BOOLEAN, -- true for Do Not Call @ sdigest BOOLEAN, -- true for daily digests only @ ssub TEXT, -- baseline subscriptions @ sctime INTDATE, -- When this entry was created. unixtime @ mtime INTDATE, -- Last change. unixtime | | > > < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > | > > | | | | < | 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 |
@ suname TEXT, -- corresponding USER entry
@ sverified BOOLEAN DEFAULT true, -- email address verified
@ sdonotcall BOOLEAN, -- true for Do Not Call
@ sdigest BOOLEAN, -- true for daily digests only
@ ssub TEXT, -- baseline subscriptions
@ sctime INTDATE, -- When this entry was created. unixtime
@ mtime INTDATE, -- Last change. unixtime
@ smip TEXT, -- IP address of last change
@ lastContact INT -- Last contact. days since 1970
@ );
@ CREATE INDEX repository.subscriberUname
@ ON subscriber(suname) WHERE suname IS NOT NULL;
@
@ DROP TABLE IF EXISTS repository.pending_alert;
@ -- Email notifications that need to be sent.
@ --
@ -- The first character of the eventid determines the event type.
@ -- Remaining characters determine the specific event. For example,
@ -- 'c4413' means check-in with rid=4413.
@ --
@ CREATE TABLE repository.pending_alert(
@ eventid TEXT PRIMARY KEY, -- Object that changed
@ sentSep BOOLEAN DEFAULT false, -- individual alert sent
@ sentDigest BOOLEAN DEFAULT false, -- digest alert sent
@ sentMod BOOLEAN DEFAULT false -- pending moderation alert sent
@ ) WITHOUT ROWID;
@
@ -- Obsolete table. No longer used.
@ DROP TABLE IF EXISTS repository.alert_bounce;
;
/*
** Return true if the email notification tables exist.
*/
int alert_tables_exist(void){
return db_table_exists("repository", "subscriber");
}
/*
** Record the fact that user zUser has made contact with the repository.
** This resets the subscription timeout on that user.
*/
void alert_user_contact(const char *zUser){
if( db_table_has_column("repository","subscriber","lastContact") ){
db_multi_exec(
"UPDATE subscriber SET lastContact=now()/86400 WHERE suname=%Q",
zUser
);
}
}
/*
** Make sure the table needed for email notification exist in the repository.
**
** If the bOnlyIfEnabled option is true, then tables are only created
** if the email-send-method is something other than "off".
*/
void alert_schema(int bOnlyIfEnabled){
if( !alert_tables_exist() ){
if( bOnlyIfEnabled
&& fossil_strcmp(db_get("email-send-method",0),"off")==0
){
return; /* Don't create table for disabled email */
}
db_exec_sql(zAlertInit);
return;
}
if( db_table_has_column("repository","subscriber","lastContact") ){
return;
}
db_multi_exec(
"DROP TABLE IF EXISTS repository.alert_bounde;\n"
"ALTER TABLE repository.subscriber ADD COLUMN lastContact INT;\n"
"UPDATE subscriber SET lastContact=mtime/86400;"
);
if( db_table_has_column("repository","pending_alert","sentMod") ){
return;
}
db_multi_exec(
"ALTER TABLE repository.pending_alert"
" ADD COLUMN sentMod BOOLEAN DEFAULT false;"
);
}
/*
** Enable triggers that automatically populate the pending_alert
** table.
*/
void alert_create_trigger(void){
|
| ︙ | ︙ | |||
268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
"enn", "", 0);
@ <p><b>Required.</b>
@ This is short name used to identifies the repository in the
@ Subject: line of email alerts. Traditionally this name is
@ included in square brackets. Examples: "[fossil-src]", "[sqlite-src]".
@ (Property: "email-subname")</p>
@ <hr>
multiple_choice_attribute("Email Send Method", "email-send-method", "esm",
"off", count(azSendMethods)/2, azSendMethods);
@ <p>How to send email. Requires auxiliary information from the fields
@ that follow. Hint: Use the <a href="%R/announce">/announce</a> page
@ to send test message to debug this setting.
@ (Property: "email-send-method")</p>
| > > > > > > > > > > > > > > | 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 |
"enn", "", 0);
@ <p><b>Required.</b>
@ This is short name used to identifies the repository in the
@ Subject: line of email alerts. Traditionally this name is
@ included in square brackets. Examples: "[fossil-src]", "[sqlite-src]".
@ (Property: "email-subname")</p>
@ <hr>
entry_attribute("Subscription Renewal Interval In Days", 8,
"email-renew-interval", "eri", "", 0);
@ <p>
@ If this value is a integer N greater than or equal to 14, then email
@ notification subscriptions will be suspended N days after the last known
@ interaction with the user. This prevents sending notifications
@ to abandoned accounts. If a subscription comes within 7 days of expiring,
@ a separate email goes out with the daily digest that prompts the
@ subscriber to click on a link to the "/renew" webpage in order to
@ extend their subscription. Subscriptions never expire if this setting
@ is less than 14 or is an empty string.
@ (Property: "email-renew-interval")</p>
@ <hr>
multiple_choice_attribute("Email Send Method", "email-send-method", "esm",
"off", count(azSendMethods)/2, azSendMethods);
@ <p>How to send email. Requires auxiliary information from the fields
@ that follow. Hint: Use the <a href="%R/announce">/announce</a> page
@ to send test message to debug this setting.
@ (Property: "email-send-method")</p>
|
| ︙ | ︙ | |||
936 937 938 939 940 941 942 943 944 945 946 947 948 949 | */ /* ** SETTING: email-subname width=16 ** This is a short name used to identifies the repository in the Subject: ** line of email alerts. Traditionally this name is included in square ** brackets. Examples: "[fossil-src]", "[sqlite-src]". */ /* ** SETTING: email-send-method width=5 default=off sensitive ** Determine the method used to send email. Allowed values are ** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value ** means no email is ever sent. The "relay" value means emails are sent ** to an Mail Sending Agent using SMTP located at email-send-relayhost. ** The "pipe" value means email messages are piped into a command | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | */ /* ** SETTING: email-subname width=16 ** This is a short name used to identifies the repository in the Subject: ** line of email alerts. Traditionally this name is included in square ** brackets. Examples: "[fossil-src]", "[sqlite-src]". */ /* ** SETTING: email-renew-interval width=16 ** If this setting as an integer N that is 14 or greater then email ** notification is suspected for subscriptions that have a "last contact ** time" of more than N days ago. The "last contact time" is recorded ** in the SUBSCRIBER.LASTCONTACT entry of the database. Logging in, ** sending a forum post, editing a wiki page, changing subscription settings ** at /alerts, or visiting /renew all update the last contact time. ** If this setting is not an integer value or is less than 14 or undefined, ** then subscriptions never expire. */ /* X-VARIABLE: email-renew-warning ** X-VARIABLE: email-renew-cutoff ** ** These CONFIG table entries are not considered "settings" since their ** values are computed and updated automatically. ** ** email-renew-cutoff is the lastContact cutoff for subscription. It ** is measured in days since 1970-01-01. If The lastContact time for ** a subscription is less than email-renew-cutoff, then now new emails ** are sent to the subscriber. ** ** email-renew-warning is the time (in days since 1970-01-01) when the ** last batch of "your subscription is about to expire" emails were ** sent out. ** ** email-renew-cutoff is normally 7 days behind email-renew-warning. */ /* ** SETTING: email-send-method width=5 default=off sensitive ** Determine the method used to send email. Allowed values are ** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value ** means no email is ever sent. The "relay" value means emails are sent ** to an Mail Sending Agent using SMTP located at email-send-relayhost. ** The "pipe" value means email messages are piped into a command |
| ︙ | ︙ | |||
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | ** send Compose and send pending email alerts. ** Some installations may want to do this via ** a cron-job to make sure alerts are sent ** in a timely manner. ** Options: ** ** --digest Send digests ** --test Write to standard output ** ** settings [NAME VALUE] With no arguments, list all email settings. ** Or change the value of a single email setting. ** ** status Report on the status of the email alert ** subsystem ** | > > | > | | | | | 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 |
** send Compose and send pending email alerts.
** Some installations may want to do this via
** a cron-job to make sure alerts are sent
** in a timely manner.
** Options:
**
** --digest Send digests
** --renewal Send subscription renewal
** notices
** --test Write to standard output
**
** settings [NAME VALUE] With no arguments, list all email settings.
** Or change the value of a single email setting.
**
** status Report on the status of the email alert
** subsystem
**
** subscribers [PATTERN] List all subscribers matching PATTERN. Either
** LIKE or GLOB wildcards can be used in PATTERN.
**
** test-message TO [OPTS] Send a single email message using whatever
** email sending mechanism is currently configured.
** Use this for testing the email notification
** configuration. Options:
**
** --body FILENAME Content from FILENAME
** --smtp-trace Trace SMTP processing
** --stdout Send msg to stdout
** -S|--subject SUBJECT Message "subject:"
**
** unsubscribe EMAIL Remove a single subscriber with the given EMAIL.
*/
void alert_cmd(void){
const char *zCmd;
int nCmd;
db_find_and_open_repository(0, 0);
|
| ︙ | ︙ | |||
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 |
);
alert_schema(0);
}
}else
if( strncmp(zCmd, "send", nCmd)==0 ){
u32 eFlags = 0;
if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST;
if( find_option("test",0,0)!=0 ){
eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT;
}
verify_all_options();
alert_send_alerts(eFlags);
}else
if( strncmp(zCmd, "settings", nCmd)==0 ){
| > | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 |
);
alert_schema(0);
}
}else
if( strncmp(zCmd, "send", nCmd)==0 ){
u32 eFlags = 0;
if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST;
if( find_option("renewal",0,0)!=0 ) eFlags |= SENDALERT_RENEWAL;
if( find_option("test",0,0)!=0 ){
eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT;
}
verify_all_options();
alert_send_alerts(eFlags);
}else
if( strncmp(zCmd, "settings", nCmd)==0 ){
|
| ︙ | ︙ | |||
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 |
pSetting = setting_info(&nSetting);
for(; nSetting>0; nSetting--, pSetting++ ){
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
print_setting(pSetting);
}
}else
if( strncmp(zCmd, "status", nCmd)==0 ){
int nSetting, n;
static const char *zFmt = "%-29s %d\n";
const Setting *pSetting = setting_info(&nSetting);
db_open_config(1, 0);
verify_all_options();
if( g.argc!=3 ) usage("status");
pSetting = setting_info(&nSetting);
for(; nSetting>0; nSetting--, pSetting++ ){
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
print_setting(pSetting);
}
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-alerts", n);
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentDigest");
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-digest-alerts", n);
n = db_int(0,"SELECT count(*) FROM subscriber");
fossil_print(zFmt/*works-like:"%s%d"*/, "total-subscribers", n);
n = db_int(0, "SELECT count(*) FROM subscriber WHERE sverified"
| > > > > > > > > > > > > > > > > > > > | > | 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 |
pSetting = setting_info(&nSetting);
for(; nSetting>0; nSetting--, pSetting++ ){
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
print_setting(pSetting);
}
}else
if( strncmp(zCmd, "status", nCmd)==0 ){
Stmt q;
int iCutoff;
int nSetting, n;
static const char *zFmt = "%-29s %d\n";
const Setting *pSetting = setting_info(&nSetting);
db_open_config(1, 0);
verify_all_options();
if( g.argc!=3 ) usage("status");
pSetting = setting_info(&nSetting);
for(; nSetting>0; nSetting--, pSetting++ ){
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
print_setting(pSetting);
}
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-alerts", n);
n = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentDigest");
fossil_print(zFmt/*works-like:"%s%d"*/, "pending-digest-alerts", n);
db_prepare(&q,
"SELECT"
" name,"
" value,"
" now()/86400-value,"
" date(value*86400,'unixepoch')"
" FROM repository.config"
" WHERE name in ('email-renew-warning','email-renew-cutoff');");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%-29s %-6d (%d days ago on %s)\n",
db_column_text(&q, 0),
db_column_int(&q, 1),
db_column_int(&q, 2),
db_column_text(&q, 3));
}
db_finalize(&q);
n = db_int(0,"SELECT count(*) FROM subscriber");
fossil_print(zFmt/*works-like:"%s%d"*/, "total-subscribers", n);
iCutoff = db_get_int("email-renew-cutoff", 0);
n = db_int(0, "SELECT count(*) FROM subscriber WHERE sverified"
" AND NOT sdonotcall AND length(ssub)>1"
" AND lastContact>=%d", iCutoff);
fossil_print(zFmt/*works-like:"%s%d"*/, "active-subscribers", n);
}else
if( strncmp(zCmd, "subscribers", nCmd)==0 ){
Stmt q;
verify_all_options();
if( g.argc!=3 && g.argc!=4 ) usage("subscribers [PATTERN]");
if( g.argc==4 ){
|
| ︙ | ︙ | |||
1389 1390 1391 1392 1393 1394 1395 |
if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
if( g.perm.RdForum && PB("sx") ) ssub[nsub++] = 'x';
ssub[nsub] = 0;
zCode = db_text(0,
"INSERT INTO subscriber(semail,suname,"
| | | | 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 |
if( g.perm.RdForum && PB("sf") ) ssub[nsub++] = 'f';
if( g.perm.RdTkt && PB("st") ) ssub[nsub++] = 't';
if( g.perm.RdWiki && PB("sw") ) ssub[nsub++] = 'w';
if( g.perm.RdForum && PB("sx") ) ssub[nsub++] = 'x';
ssub[nsub] = 0;
zCode = db_text(0,
"INSERT INTO subscriber(semail,suname,"
" sverified,sdonotcall,sdigest,ssub,sctime,mtime,smip,lastContact)"
"VALUES(%Q,%Q,%d,0,%d,%Q,now(),now(),%Q,now()/86400)"
"RETURNING hex(subscriberCode);",
/* semail */ zEAddr,
/* suname */ suname,
/* sverified */ needCaptcha==0,
/* sdigest */ PB("di"),
/* ssub */ ssub,
/* smip */ g.zIpAddr
|
| ︙ | ︙ | |||
1580 1581 1582 1583 1584 1585 1586 |
@ <p>Unable to locate a subscriber with the requested key</p>
}else{
db_multi_exec(
"DELETE FROM subscriber WHERE subscriberId=%d", sid
);
style_header("Unsubscribed");
| | | > | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 |
@ <p>Unable to locate a subscriber with the requested key</p>
}else{
db_multi_exec(
"DELETE FROM subscriber WHERE subscriberId=%d", sid
);
style_header("Unsubscribed");
@ <p>The "%h(zEmail)" email address has been unsubscribed from all
@ notifications. All subscription records for "%h(zEmail)" have
@ been purged. No further emails will be sent to "%h(zEmail)".</p>
if( uid && g.perm.Admin ){
@ <p>You may also want to
@ <a href="%R/setup_uedit?id=%d(uid)">edit or delete
@ the corresponding user "%h(zLogin)"</a></p>
}
}
db_finalize(&q);
|
| ︙ | ︙ | |||
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 |
const char *mtime; /* */
const char *sctime; /* Time subscription created */
int eErr = 0; /* Type of error */
char *zErr = 0; /* Error message text */
int sid = 0; /* Subscriber ID */
int nName; /* Length of zName in bytes */
char *zHalfCode; /* prefix of subscriberCode */
db_begin_transaction();
if( alert_webpages_disabled() ){
db_commit_transaction();
return;
}
login_check_credentials();
| > | 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 |
const char *mtime; /* */
const char *sctime; /* Time subscription created */
int eErr = 0; /* Type of error */
char *zErr = 0; /* Error message text */
int sid = 0; /* Subscriber ID */
int nName; /* Length of zName in bytes */
char *zHalfCode; /* prefix of subscriberCode */
int keepAlive = 0; /* True to update the last contact time */
db_begin_transaction();
if( alert_webpages_disabled() ){
db_commit_transaction();
return;
}
login_check_credentials();
|
| ︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 |
}
if( sid==0 && nName>=32 ){
sid = db_int(0,
"SELECT CASE WHEN hex(subscriberCode) LIKE (%Q||'%%')"
" THEN subscriberId ELSE 0 END"
" FROM subscriber WHERE subscriberCode>=hextoblob(%Q)"
" LIMIT 1", zName, zName);
}
if( sid==0 && isLogin ){
sid = db_int(0, "SELECT subscriberId FROM subscriber"
" WHERE suname=%Q", g.zLogin);
}
if( sid==0 ){
db_commit_transaction();
| > | 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 |
}
if( sid==0 && nName>=32 ){
sid = db_int(0,
"SELECT CASE WHEN hex(subscriberCode) LIKE (%Q||'%%')"
" THEN subscriberId ELSE 0 END"
" FROM subscriber WHERE subscriberCode>=hextoblob(%Q)"
" LIMIT 1", zName, zName);
if( sid ) keepAlive = 1;
}
if( sid==0 && isLogin ){
sid = db_int(0, "SELECT subscriberId FROM subscriber"
" WHERE suname=%Q", g.zLogin);
}
if( sid==0 ){
db_commit_transaction();
|
| ︙ | ︙ | |||
1694 1695 1696 1697 1698 1699 1700 |
newSsub[nsub] = 0;
ssub = newSsub;
blob_init(&update, "UPDATE subscriber SET", -1);
blob_append_sql(&update,
" sdonotcall=%d,"
" sdigest=%d,"
" ssub=%Q,"
| | > | 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 |
newSsub[nsub] = 0;
ssub = newSsub;
blob_init(&update, "UPDATE subscriber SET", -1);
blob_append_sql(&update,
" sdonotcall=%d,"
" sdigest=%d,"
" ssub=%Q,"
" mtime=now(),"
" lastContact=now()/86400,"
" smip=%Q",
sdonotcall,
sdigest,
ssub,
g.zIpAddr
);
if( g.perm.Admin ){
|
| ︙ | ︙ | |||
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 |
}
blob_append_sql(&update," WHERE subscriberId=%d", sid);
if( eErr==0 ){
db_exec_sql(blob_str(&update));
ssub = 0;
}
blob_reset(&update);
}
if( P("delete")!=0 && cgi_csrf_safe(1) ){
if( !PB("dodelete") ){
eErr = 9;
zErr = mprintf("Select this checkbox and press \"Unsubscribe\" again to"
" unsubscribe");
}else{
| > > > > > | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 |
}
blob_append_sql(&update," WHERE subscriberId=%d", sid);
if( eErr==0 ){
db_exec_sql(blob_str(&update));
ssub = 0;
}
blob_reset(&update);
}else if( keepAlive ){
db_multi_exec(
"UPDATE subscriber SET lastContact=now()/86400"
" WHERE subscriberId=%d", sid
);
}
if( P("delete")!=0 && cgi_csrf_safe(1) ){
if( !PB("dodelete") ){
eErr = 9;
zErr = mprintf("Select this checkbox and press \"Unsubscribe\" again to"
" unsubscribe");
}else{
|
| ︙ | ︙ | |||
1749 1750 1751 1752 1753 1754 1755 |
" sdonotcall," /* 2 */
" sdigest," /* 3 */
" ssub," /* 4 */
" smip," /* 5 */
" suname," /* 6 */
" datetime(mtime,'unixepoch')," /* 7 */
" datetime(sctime,'unixepoch')," /* 8 */
| | > > | 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 |
" sdonotcall," /* 2 */
" sdigest," /* 3 */
" ssub," /* 4 */
" smip," /* 5 */
" suname," /* 6 */
" datetime(mtime,'unixepoch')," /* 7 */
" datetime(sctime,'unixepoch')," /* 8 */
" hex(subscriberCode)," /* 9 */
" date(coalesce(lastContact*86400,mtime),'unixepoch')," /* 10 */
" now()/86400 - coalesce(lastContact,mtime/86400)" /* 11 */
" FROM subscriber WHERE subscriberId=%d", sid);
if( db_step(&q)!=SQLITE_ROW ){
db_finalize(&q);
db_commit_transaction();
cgi_redirect("subscribe");
/*NOTREACHED*/
}
|
| ︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 |
@ <td class='form_label'>IP Address:</td>
@ <td>%h(smip)</td>
@ </tr>
@ <tr>
@ <td class='form_label'>Subscriber Code:</td>
@ <td>%h(db_column_text(&q,9))</td>
@ <tr>
@ <td class="form_label">User:</td>
@ <td><input type="text" name="suname" value="%h(suname?suname:"")" \
@ size="30">\
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", suname);
if( uid ){
@ <a href='%R/setup_uedit?id=%d(uid)'>\
@ (login info for %h(suname))</a>\
| > > > > > | 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 |
@ <td class='form_label'>IP Address:</td>
@ <td>%h(smip)</td>
@ </tr>
@ <tr>
@ <td class='form_label'>Subscriber Code:</td>
@ <td>%h(db_column_text(&q,9))</td>
@ <tr>
@ <tr>
@ <td class='form_label'>Last Contact:</td>
@ <td>%h(db_column_text(&q,10)) ← \
@ %,d(db_column_int(&q,11)) days ago</td>
@ </tr>
@ <td class="form_label">User:</td>
@ <td><input type="text" name="suname" value="%h(suname?suname:"")" \
@ size="30">\
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", suname);
if( uid ){
@ <a href='%R/setup_uedit?id=%d(uid)'>\
@ (login info for %h(suname))</a>\
|
| ︙ | ︙ | |||
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 | @ </form> fossil_free(zErr); db_finalize(&q); style_finish_page(); db_commit_transaction(); return; } /* This is the message that gets sent to describe how to change ** or modify a subscription */ static const char zUnsubMsg[] = @ To changes your subscription settings at %s visit this link: @ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 |
@ </form>
fossil_free(zErr);
db_finalize(&q);
style_finish_page();
db_commit_transaction();
return;
}
/*
** WEBPAGE: renew
**
** Users visit this page to update the last-contact date on their
** subscription. The last-contact date is the day that the subscriber
** last interacted with the repository. If the name= query parameter
** (or POST parameter) contains a valid subscriber code, then the last-contact
** subscription associated with that subscriber code is updated to be the
** current date.
*/
void renewal_page(void){
const char *zName = P("name");
int iInterval = db_get_int("email-renew-interval", 0);
Stmt s;
int rc;
style_header("Subscription Renewal");
if( zName==0 || strlen(zName)<4 ){
@ <p>No subscription specified</p>
style_finish_page();
return;
}
if( !db_table_has_column("repository","subscriber","lastContact")
|| iInterval<1
){
@ <p>This repository does not expire email notification subscriptions.
@ No renewals are necessary.</p>
style_finish_page();
return;
}
db_prepare(&s,
"UPDATE subscriber"
" SET lastContact=now()/86400"
" WHERE subscriberCode=hextoblob(%Q)"
" RETURNING semail, date('now','+%d days');",
zName, iInterval+1
);
rc = db_step(&s);
if( rc==SQLITE_ROW ){
@ <p>The email notification subscription for %h(db_column_text(&s,0))
@ has been extended until %h(db_column_text(&s,1)) UTC.
}else{
@ <p>No such subscriber-id: %h(zName)</p>
}
db_finalize(&s);
style_finish_page();
}
/* This is the message that gets sent to describe how to change
** or modify a subscription
*/
static const char zUnsubMsg[] =
@ To changes your subscription settings at %s visit this link:
@
|
| ︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 |
void subscriber_list_page(void){
Blob sql;
Stmt q;
sqlite3_int64 iNow;
int nTotal;
int nPending;
int nDel = 0;
if( alert_webpages_disabled() ) return;
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
alert_submenu_common();
style_submenu_element("Users","setup_ulist");
style_set_current_feature("alerts");
style_header("Subscriber List");
nTotal = db_int(0, "SELECT count(*) FROM subscriber");
nPending = db_int(0, "SELECT count(*) FROM subscriber WHERE NOT sverified");
if( nPending>0 && P("purge") && cgi_csrf_safe(0) ){
int nNewPending;
db_multi_exec(
"DELETE FROM subscriber"
| > > > > | | | > > > | > > > > > > > > > > > > | 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 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 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 |
void subscriber_list_page(void){
Blob sql;
Stmt q;
sqlite3_int64 iNow;
int nTotal;
int nPending;
int nDel = 0;
int iCutoff = db_get_int("email-renew-cutoff",0);
int iWarning = db_get_int("email-renew-warning",0);
char zCutoffClr[8];
char zWarnClr[8];
if( alert_webpages_disabled() ) return;
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
alert_submenu_common();
style_submenu_element("Users","setup_ulist");
style_set_current_feature("alerts");
style_header("Subscriber List");
nTotal = db_int(0, "SELECT count(*) FROM subscriber");
nPending = db_int(0, "SELECT count(*) FROM subscriber WHERE NOT sverified");
if( nPending>0 && P("purge") && cgi_csrf_safe(0) ){
int nNewPending;
db_multi_exec(
"DELETE FROM subscriber"
" WHERE NOT sverified AND mtime<now()-86400"
);
nNewPending = db_int(0, "SELECT count(*) FROM subscriber"
" WHERE NOT sverified");
nDel = nPending - nNewPending;
nPending = nNewPending;
nTotal -= nDel;
}
if( nPending>0 ){
@ <h1>%,d(nTotal) Subscribers, %,d(nPending) Pending</h1>
if( nDel==0 && 0<db_int(0,"SELECT count(*) FROM subscriber"
" WHERE NOT sverified AND mtime<now()-86400")
){
style_submenu_element("Purge Pending","subscribers?purge");
}
}else{
@ <h1>%,d(nTotal) Subscribers</h1>
}
if( nDel>0 ){
@ <p>*** %d(nDel) pending subscriptions deleted ***</p>
}
blob_init(&sql, 0, 0);
blob_append_sql(&sql,
"SELECT subscriberId," /* 0 */
" semail," /* 1 */
" ssub," /* 2 */
" suname," /* 3 */
" sverified," /* 4 */
" sdigest," /* 5 */
" mtime," /* 6 */
" date(sctime,'unixepoch')," /* 7 */
" (SELECT uid FROM user WHERE login=subscriber.suname)," /* 8 */
" coalesce(lastContact,mtime/86400)" /* 9 */
" FROM subscriber"
);
if( P("only")!=0 ){
blob_append_sql(&sql, " WHERE ssub LIKE '%%%q%%'", P("only"));
style_submenu_element("Show All","%R/subscribers");
}
blob_append_sql(&sql," ORDER BY mtime DESC");
db_prepare_blob(&q, &sql);
iNow = time(0);
memcpy(zCutoffClr, hash_color("A"), sizeof(zCutoffClr));
memcpy(zWarnClr, hash_color("HIJ"), sizeof(zWarnClr));
@ <table border='1' class='sortable' \
@ data-init-sort='6' data-column-types='tttttKKt'>
@ <thead>
@ <tr>
@ <th>Email
@ <th>Events
@ <th>Digest-Only?
@ <th>User
@ <th>Verified?
@ <th>Last change
@ <th>Last contact
@ <th>Created
@ </tr>
@ </thead><tbody>
while( db_step(&q)==SQLITE_ROW ){
sqlite3_int64 iMtime = db_column_int64(&q, 6);
double rAge = (iNow - iMtime)/86400.0;
int uid = db_column_int(&q, 8);
const char *zUname = db_column_text(&q, 3);
sqlite3_int64 iContact = db_column_int64(&q, 9);
double rContact = (iNow/86400) - iContact;
@ <tr>
@ <td><a href='%R/alerts?sid=%d(db_column_int(&q,0))'>\
@ %h(db_column_text(&q,1))</a></td>
@ <td>%h(db_column_text(&q,2))</td>
@ <td>%s(db_column_int(&q,5)?"digest":"")</td>
if( uid ){
@ <td><a href='%R/setup_uedit?id=%d(uid)'>%h(zUname)</a>
}else{
@ <td>%h(zUname)</td>
}
@ <td>%s(db_column_int(&q,4)?"yes":"pending")</td>
@ <td data-sortkey='%010llx(iMtime)'>%z(human_readable_age(rAge))</td>
@ <td data-sortkey='%010llx(iContact)'>\
if( iContact>iWarning ){
@ <span>\
}else if( iContact>iCutoff ){
@ <span style='background-color:%s(zWarnClr);'>\
}else{
@ <span style='background-color:%s(zCutoffClr);'>\
}
@ %z(human_readable_age(rContact))</td>
@ <td>%h(db_column_text(&q,7))</td>
@ </tr>
}
@ </tbody></table>
db_finalize(&q);
style_table_sorter();
style_finish_page();
|
| ︙ | ︙ | |||
2418 2419 2420 2421 2422 2423 2424 |
blob_appendf(pOut,
"This is an automated email reporting changes "
"on Fossil repository %s (%s/timeline)\n",
db_get("email-subname","(unknown)"),
db_get("email-url","http://localhost:8080"));
}
| < < < < < < < < < | > | > | > > > > > > | 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 |
blob_appendf(pOut,
"This is an automated email reporting changes "
"on Fossil repository %s (%s/timeline)\n",
db_get("email-subname","(unknown)"),
db_get("email-url","http://localhost:8080"));
}
/*
** COMMAND: test-alert
**
** Usage: %fossil test-alert EVENTID ...
**
** Generate the text of an email alert for all of the EVENTIDs
** listed on the command-line. Or if no events are listed on the
** command line, generate text for all events named in the
** pending_alert table. The text of the email alerts appears on
** standard output.
**
** This command is intended for testing and debugging Fossil itself,
** for example when enhancing the email alert system or fixing bugs
** in the email alert system. If you are not making changes to the
** Fossil source code, this command is probably not useful to you.
**
** EVENTIDs are text. The first character is 'c', 'f', 't', or 'w'
** for check-in, forum, ticket, or wiki. The remaining text is a
** integer that references the EVENT.OBJID value for the event.
** Run /timeline?showid to see these OBJID values.
**
** Options:
**
** --digest Generate digest alert text
** --needmod Assume all events are pending moderator approval
*/
void test_alert_cmd(void){
|
| ︙ | ︙ | |||
2482 2483 2484 2485 2486 2487 2488 |
if( blob_size(&p->hdr) ){
blob_append(&out, blob_buffer(&p->hdr), blob_size(&p->hdr));
blob_append(&out, "\n", 1);
}
blob_append(&out, blob_buffer(&p->txt), blob_size(&p->txt));
}
alert_free_eventlist(pEvent);
| < | 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 |
if( blob_size(&p->hdr) ){
blob_append(&out, blob_buffer(&p->hdr), blob_size(&p->hdr));
blob_append(&out, "\n", 1);
}
blob_append(&out, blob_buffer(&p->txt), blob_size(&p->txt));
}
alert_free_eventlist(pEvent);
fossil_print("%s", blob_str(&out));
blob_reset(&out);
db_end_transaction(0);
}
/*
** COMMAND: test-add-alerts
|
| ︙ | ︙ | |||
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 |
db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]);
}
db_end_transaction(0);
if( doAuto ){
alert_backoffice(SENDALERT_TRACE|mFlags);
}
}
#if INTERFACE
/*
** Flags for alert_send_alerts()
*/
#define SENDALERT_DIGEST 0x0001 /* Send a digest */
#define SENDALERT_PRESERVE 0x0002 /* Do not mark the task as done */
#define SENDALERT_STDOUT 0x0004 /* Print emails instead of sending */
#define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */
#endif /* INTERFACE */
/*
** Send alert emails to subscribers.
**
** This procedure is run by either the backoffice, or in response to the
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 |
db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]);
}
db_end_transaction(0);
if( doAuto ){
alert_backoffice(SENDALERT_TRACE|mFlags);
}
}
/*
** Minimum number of days between renewal messages
*/
#define ALERT_RENEWAL_MSG_FREQUENCY 7 /* Do renewals at most once/week */
/*
** Construct the header and body for an email message that will alert
** a subscriber that their subscriptions are about to expire.
*/
static void alert_renewal_msg(
Blob *pHdr, /* Write email header here */
Blob *pBody, /* Write email body here */
const char *zCode, /* The subscriber code */
int lastContact, /* Last contact (days since 1970) */
const char *zEAddr, /* Subscriber email address. Send to this. */
const char *zSub, /* Subscription codes */
const char *zRepoName, /* Name of the sending Fossil repostory */
const char *zUrl /* URL for the sending Fossil repostory */
){
blob_appendf(pHdr,"To: <%s>\r\n", zEAddr);
blob_appendf(pHdr,"Subject: %s Subscription to %s expires soon\r\n",
zRepoName, zUrl);
blob_appendf(pBody,
"\nTo renew your subscription, click the following link:\n"
"\n %s/renew/%s\n\n",
zUrl, zCode
);
blob_appendf(pBody,
"You are currently receiving email notification for the following events\n"
"on the %s Fossil repository at %s:\n\n",
zRepoName, zUrl
);
if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n");
if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n");
if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n");
if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n");
if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n");
blob_appendf(pBody, "\n"
"If you take no action, your subscription will expire and you will be\n"
"unsubscribed in about %d days. To make other changes or to unsubscribe\n"
"immediately, visit the following webpage:\n\n"
" %s/alerts/%s\n\n",
ALERT_RENEWAL_MSG_FREQUENCY, zUrl, zCode
);
}
#if INTERFACE
/*
** Flags for alert_send_alerts()
*/
#define SENDALERT_DIGEST 0x0001 /* Send a digest */
#define SENDALERT_PRESERVE 0x0002 /* Do not mark the task as done */
#define SENDALERT_STDOUT 0x0004 /* Print emails instead of sending */
#define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */
#define SENDALERT_RENEWAL 0x0010 /* Send renewal notices */
#endif /* INTERFACE */
/*
** Send alert emails to subscribers.
**
** This procedure is run by either the backoffice, or in response to the
|
| ︙ | ︙ | |||
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 |
Blob hdr, body;
const char *zUrl;
const char *zRepoName;
const char *zFrom;
const char *zDest = (flags & SENDALERT_STDOUT) ? "stdout" : 0;
AlertSender *pSender = 0;
u32 senderFlags = 0;
if( g.fSqlTrace ) fossil_trace("-- BEGIN alert_send_alerts(%u)\n", flags);
alert_schema(0);
| > | | 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 |
Blob hdr, body;
const char *zUrl;
const char *zRepoName;
const char *zFrom;
const char *zDest = (flags & SENDALERT_STDOUT) ? "stdout" : 0;
AlertSender *pSender = 0;
u32 senderFlags = 0;
int iInterval = 0; /* Subscription renewal interval */
if( g.fSqlTrace ) fossil_trace("-- BEGIN alert_send_alerts(%u)\n", flags);
alert_schema(0);
if( !alert_enabled() && (flags & SENDALERT_STDOUT)==0 ) goto send_alert_done;
zUrl = db_get("email-url",0);
if( zUrl==0 ) goto send_alert_done;
zRepoName = db_get("email-subname",0);
if( zRepoName==0 ) goto send_alert_done;
zFrom = db_get("email-self",0);
if( zFrom==0 ) goto send_alert_done;
if( flags & SENDALERT_TRACE ){
|
| ︙ | ︙ | |||
2645 2646 2647 2648 2649 2650 2651 |
);
}
/* Step 2: compute EmailEvent objects for every notification that
** needs sending.
*/
pEvents = alert_compute_event_text(&nEvent, (flags & SENDALERT_DIGEST)!=0);
| | | 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 |
);
}
/* Step 2: compute EmailEvent objects for every notification that
** needs sending.
*/
pEvents = alert_compute_event_text(&nEvent, (flags & SENDALERT_DIGEST)!=0);
if( nEvent==0 ) goto send_alert_expiration_warnings;
/* Step 4a: Update the pending_alerts table to designate the
** alerts as having all been sent. This is done *before* step (3)
** so that a crash will not cause alerts to be sent multiple times.
** Better a missed alert than being spammed with hundreds of alerts
** due to a bug.
*/
|
| ︙ | ︙ | |||
2680 2681 2682 2683 2684 2685 2686 |
db_prepare(&q,
"SELECT"
" hex(subscriberCode)," /* 0 */
" semail," /* 1 */
" ssub," /* 2 */
" fullcap(user.cap)" /* 3 */
" FROM subscriber LEFT JOIN user ON (login=suname)"
| | > | > | > | 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 |
db_prepare(&q,
"SELECT"
" hex(subscriberCode)," /* 0 */
" semail," /* 1 */
" ssub," /* 2 */
" fullcap(user.cap)" /* 3 */
" FROM subscriber LEFT JOIN user ON (login=suname)"
" WHERE sverified"
" AND NOT sdonotcall"
" AND sdigest IS %s"
" AND coalesce(subscriber.lastContact,subscriber.mtime)>=%d",
zDigest/*safe-for-%s*/,
db_get_int("email-renew-cutoff",0)
);
while( db_step(&q)==SQLITE_ROW ){
const char *zCode = db_column_text(&q, 0);
const char *zSub = db_column_text(&q, 2);
const char *zEmail = db_column_text(&q, 1);
const char *zCap = db_column_text(&q, 3);
int nHit = 0;
|
| ︙ | ︙ | |||
2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 |
}
nHit++;
blob_append(&body, "\n", 1);
blob_append(&body, blob_buffer(&p->txt), blob_size(&p->txt));
}
}
if( nHit==0 ) continue;
blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
zUrl, zCode);
alert_send(pSender,&hdr,&body,0);
nSent++;
blob_truncate(&hdr, 0);
blob_truncate(&body, 0);
}
blob_reset(&hdr);
blob_reset(&body);
db_finalize(&q);
alert_free_eventlist(pEvents);
/* Step 4b: Update the pending_alerts table to remove all of the
** alerts that have been completely sent.
*/
db_multi_exec("DELETE FROM pending_alert WHERE sentDigest AND sentSep;");
send_alert_done:
alert_sender_free(pSender);
if( g.fSqlTrace ) fossil_trace("-- END alert_send_alerts(%u)\n", flags);
return nSent;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 |
}
nHit++;
blob_append(&body, "\n", 1);
blob_append(&body, blob_buffer(&p->txt), blob_size(&p->txt));
}
}
if( nHit==0 ) continue;
blob_appendf(&hdr, "List-Unsubscribe: <%s/unsubscribe/%s>\r\n",
zUrl, zCode);
blob_appendf(&hdr, "List-Unsubscribe-Post: List-Unsubscribe=One-Click\r\n");
blob_appendf(&body,"\n-- \nSubscription info: %s/alerts/%s\n",
zUrl, zCode);
alert_send(pSender,&hdr,&body,0);
nSent++;
blob_truncate(&hdr, 0);
blob_truncate(&body, 0);
}
blob_reset(&hdr);
blob_reset(&body);
db_finalize(&q);
alert_free_eventlist(pEvents);
/* Step 4b: Update the pending_alerts table to remove all of the
** alerts that have been completely sent.
*/
db_multi_exec("DELETE FROM pending_alert WHERE sentDigest AND sentSep;");
/* Send renewal messages to subscribers whose subscriptions are about
** to expire. Only do this if:
**
** (1) email-renew-interval is 14 or greater (or in other words if
** subscription expiration is enabled).
**
** (2) The SENDALERT_RENEWAL flag is set
*/
send_alert_expiration_warnings:
if( (flags & SENDALERT_RENEWAL)!=0
&& (iInterval = db_get_int("email-renew-interval",0))>=14
){
int iNow = (int)(time(0)/86400);
int iOldWarn = db_get_int("email-renew-warning",0);
int iNewWarn = iNow - iInterval + ALERT_RENEWAL_MSG_FREQUENCY;
if( iNewWarn >= iOldWarn + ALERT_RENEWAL_MSG_FREQUENCY ){
db_prepare(&q,
"SELECT"
" hex(subscriberCode)," /* 0 */
" lastContact," /* 1 */
" semail," /* 2 */
" ssub" /* 3 */
" FROM subscriber"
" WHERE lastContact<=%d AND lastContact>%d"
" AND NOT sdonotcall"
" AND length(sdigest)>0",
iNewWarn, iOldWarn
);
while( db_step(&q)==SQLITE_ROW ){
Blob hdr, body;
blob_init(&hdr, 0, 0);
blob_init(&body, 0, 0);
alert_renewal_msg(&hdr, &body,
db_column_text(&q,0),
db_column_int(&q,1),
db_column_text(&q,2),
db_column_text(&q,3),
zRepoName, zUrl);
alert_send(pSender,&hdr,&body,0);
blob_reset(&hdr);
blob_reset(&body);
}
db_finalize(&q);
if( (flags & SENDALERT_PRESERVE)==0 ){
if( iOldWarn>0 ){
db_set_int("email-renew-cutoff", iOldWarn, 0);
}
db_set_int("email-renew-warning", iNewWarn, 0);
}
}
}
send_alert_done:
alert_sender_free(pSender);
if( g.fSqlTrace ) fossil_trace("-- END alert_send_alerts(%u)\n", flags);
return nSent;
}
|
| ︙ | ︙ | |||
2793 2794 2795 2796 2797 2798 2799 |
int iJulianDay;
int nSent = 0;
if( !alert_tables_exist() ) return 0;
nSent = alert_send_alerts(mFlags);
iJulianDay = db_int(0, "SELECT julianday('now')");
if( iJulianDay>db_get_int("email-last-digest",0) ){
db_set_int("email-last-digest",iJulianDay,0);
| | | 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 |
int iJulianDay;
int nSent = 0;
if( !alert_tables_exist() ) return 0;
nSent = alert_send_alerts(mFlags);
iJulianDay = db_int(0, "SELECT julianday('now')");
if( iJulianDay>db_get_int("email-last-digest",0) ){
db_set_int("email-last-digest",iJulianDay,0);
nSent += alert_send_alerts(SENDALERT_DIGEST|SENDALERT_RENEWAL|mFlags);
}
return nSent;
}
/*
** WEBPAGE: contact_admin
**
|
| ︙ | ︙ |
Changes to src/backlink.c.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
@ <td><a href="%R/info?name=rid:%d(srcid)">ticket-%d(srcid)</a>
break;
}
case BKLNK_WIKI: {
const char *zName = db_column_text(&q, 4);
@ <td><a href="%R/wiki?name=%h(zName)&p">wiki-%d(srcid)</a>
break;
}
default: {
@ <td>unknown(%d(srctype)) - %d(srcid)
break;
}
}
@ <td>%h(zMtime)</tr>
| > > > > > > > > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
@ <td><a href="%R/info?name=rid:%d(srcid)">ticket-%d(srcid)</a>
break;
}
case BKLNK_WIKI: {
const char *zName = db_column_text(&q, 4);
@ <td><a href="%R/wiki?name=%h(zName)&p">wiki-%d(srcid)</a>
break;
}
case BKLNK_EVENT: {
@ <td><a href="%R/info?name=rid:%d(srcid)">tecknote-%d(srcid)</a>
break;
}
case BKLNK_FORUM: {
@ <td><a href="%R/info?name=rid:%d(srcid)">forum-%d(srcid)</a>
break;
}
default: {
@ <td>unknown(%d(srctype)) - %d(srcid)
break;
}
}
@ <td>%h(zMtime)</tr>
|
| ︙ | ︙ |
Changes to src/branch.c.
| ︙ | ︙ | |||
361 362 363 364 365 366 367 368 369 370 371 372 373 374 | ** > fossil branch list|ls ?OPTIONS? ?GLOB? ** ** List all branches. Options: ** -a|--all List all branches. Default show only open branches ** -c|--closed List closed branches. ** -r Reverse the sort order ** -t Show recently changed branches first ** ** If GLOB is given, show only branches matching the pattern. ** ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: | > > | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | ** > fossil branch list|ls ?OPTIONS? ?GLOB? ** ** List all branches. Options: ** -a|--all List all branches. Default show only open branches ** -c|--closed List closed branches. ** -r Reverse the sort order ** -t Show recently changed branches first ** ** The current branch is marked with an asterisk. ** ** If GLOB is given, show only branches matching the pattern. ** ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS? ** ** Create a new branch BRANCH-NAME off of check-in BASIS. ** Supported options for this subcommand include: |
| ︙ | ︙ | |||
470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_checkbox("colors", "Use Branch Colors", 0, 0);
login_anonymous_available();
brlist_create_temp_table();
db_prepare(&q, "SELECT * FROM tmp_brlist ORDER BY mtime DESC");
rNow = db_double(0.0, "SELECT julianday('now')");
@ <div class="brlist">
@ <table class='sortable' data-column-types='tkNtt' data-init-sort='2'>
@ <thead><tr>
@ <th>Branch Name</th>
@ <th>Last Change</th>
@ <th>Check-ins</th>
@ <th>Status</th>
| > > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
style_adunit_config(ADUNIT_RIGHT_OK);
style_submenu_checkbox("colors", "Use Branch Colors", 0, 0);
login_anonymous_available();
brlist_create_temp_table();
db_prepare(&q, "SELECT * FROM tmp_brlist ORDER BY mtime DESC");
rNow = db_double(0.0, "SELECT julianday('now')");
@ <script id="brlist-data" type="application/json">\
@ {"timelineUrl":"%R/timeline"}</script>
@ <div class="brlist">
@ <table class='sortable' data-column-types='tkNtt' data-init-sort='2'>
@ <thead><tr>
@ <th>Branch Name</th>
@ <th>Last Change</th>
@ <th>Check-ins</th>
@ <th>Status</th>
|
| ︙ | ︙ | |||
502 503 504 505 506 507 508 |
}
}
if( zBgClr && zBgClr[0] && show_colors ){
@ <tr style="background-color:%s(zBgClr)">
}else{
@ <tr>
}
| | > > | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
}
}
if( zBgClr && zBgClr[0] && show_colors ){
@ <tr style="background-color:%s(zBgClr)">
}else{
@ <tr>
}
@ <td>%z(href("%R/timeline?r=%T",zBranch))%h(zBranch)</a><input
@ type="checkbox" disabled="disabled"/></td>
@ <td data-sortkey="%016llx(iMtime)">%s(zAge)</td>
@ <td>%d(nCkin)</td>
fossil_free(zAge);
@ <td>%s(isClosed?"closed":"")</td>
if( zMergeTo ){
@ <td>merged into
@ %z(href("%R/timeline?f=%!S",zLastCkin))%h(zMergeTo)</a></td>
}else{
@ <td></td>
}
@ </tr>
}
@ </tbody></table></div>
db_finalize(&q);
builtin_request_js("fossil.page.brlist.js");
style_table_sorter();
style_finish_page();
}
/*
** WEBPAGE: brlist
** Show a list of branches. With no query parameters, a sortable table
|
| ︙ | ︙ |
Changes to src/bundle.c.
| ︙ | ︙ | |||
58 59 60 61 62 63 64 |
char *zErrMsg = 0;
char *zSql;
if( !doInit && file_size(zFile, ExtFILE)<0 ){
fossil_fatal("no such file: %s", zFile);
}
assert( g.db );
zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName);
| | | | | 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 |
char *zErrMsg = 0;
char *zSql;
if( !doInit && file_size(zFile, ExtFILE)<0 ){
fossil_fatal("no such file: %s", zFile);
}
assert( g.db );
zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
sqlite3_free(zSql);
if( rc!=SQLITE_OK || zErrMsg ){
if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db);
fossil_fatal("not a valid bundle: %s", zFile);
}
if( doInit ){
db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName);
}else{
sqlite3_stmt *pStmt;
zSql = sqlite3_mprintf("SELECT bcname, bcvalue"
" FROM \"%w\".bconfig", zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
sqlite3_free(zSql);
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf("SELECT blobid, uuid, sz, delta, notes, data"
" FROM \"%w\".bblob", zBName);
if( zSql==0 ) fossil_fatal("out of memory");
rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0);
if( rc ) fossil_fatal("not a valid bundle: %s", zFile);
sqlite3_free(zSql);
sqlite3_finalize(pStmt);
}
}
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
1834 1835 1836 1837 1838 1839 1840 |
#endif
if( zIpAddr ){
if( nCycles==0 ){
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
}
}else{
| | | 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 |
#endif
if( zIpAddr ){
if( nCycles==0 ){
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = fossil_strdup(zIpAddr);
}
}else{
fossil_fatal("missing SSH IP address");
}
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
malformed_request("missing HTTP header");
}
cgi_trace(zLine);
zToken = extract_token(zLine, &z);
if( zToken==0 ){
|
| ︙ | ︙ |
Changes to src/chat.c.
| ︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
** chat messages, and waits for new one.
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
char *zAlert;
login_check_credentials();
if( !g.perm.Chat ){
login_needed(g.anon.Chat);
return;
}
zAlert = mprintf("%s/builtin/%s", g.zBaseURL,
db_get("chat-alert-sound","alerts/plunk.wav"));
style_set_current_feature("chat");
style_header("Chat");
@ <form accept-encoding="utf-8" id="chat-form" autocomplete="off">
@ <div id='chat-input-area'>
@ <div id='chat-input-line'>
@ <input type="text" name="msg" id="chat-input-single" \
| > > | | < < | | 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 |
** chat messages, and waits for new one.
**
** Other /chat-OP pages are used by XHR requests from this page to
** send new chat message, delete older messages, or poll for changes.
*/
void chat_webpage(void){
char *zAlert;
char *zProjectName;
login_check_credentials();
if( !g.perm.Chat ){
login_needed(g.anon.Chat);
return;
}
zAlert = mprintf("%s/builtin/%s", g.zBaseURL,
db_get("chat-alert-sound","alerts/plunk.wav"));
zProjectName = db_get("project-name","Unnamed project");
style_set_current_feature("chat");
style_header("Chat");
@ <form accept-encoding="utf-8" id="chat-form" autocomplete="off">
@ <div id='chat-input-area'>
@ <div id='chat-input-line'>
@ <input type="text" name="msg" id="chat-input-single" \
@ placeholder="Type message for %h(zProjectName)." autocomplete="off">
@ <textarea rows="8" id="chat-input-multi" \
@ placeholder="Type message for %h(zProjectName). Ctrl-Enter sends it." \
@ class="hidden"></textarea>
@ <input type="submit" value="Send" id="chat-message-submit">
@ <span id="chat-settings-button" class="settings-icon" \
@ aria-label="Settings..." aria-haspopup="true" ></span>
@ </div>
@ <div id='chat-input-file-area'>
@ <div class='file-selection-wrapper'>
@ <div class='help-buttonlet'>
@ Select a file to upload, drag/drop a file into this spot,
@ or paste an image from the clipboard if supported by
@ your environment.
@ </div>
@ <input type="file" name="file" id="chat-input-file">
@ </div>
@ <div id="chat-drop-details"></div>
@ </div>
@ </div>
@ </form>
@ <div id='chat-messages-wrapper'>
/* New chat messages get inserted immediately after this element */
@ <span id='message-inject-point'></span>
@ </div>
fossil_free(zProjectName);
builtin_fossil_js_bundle_or("popupwidget", "storage", "fetch", NULL);
/* Always in-line the javascript for the chat page */
@ <script nonce="%h(style_nonce())">/* chat.c:%d(__LINE__) */
/* We need an onload handler to ensure that window.fossil is
initialized before the chat init code runs. */
@ window.addEventListener('load', function(){
@ document.body.classList.add('chat')
|
| ︙ | ︙ | |||
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
** 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;
login_check_credentials();
if( !g.perm.Chat ) {
chat_emit_permissions_error(0);
return;
}
chat_create_tables();
nByte = atoi(PD("file:bytes","0"));
zMsg = PD("msg","");
db_begin_write();
chat_purge();
if( nByte==0 ){
if( zMsg[0] ){
db_multi_exec(
"INSERT INTO chat(mtime,lmtime,xfrom,xmsg)"
"VALUES(julianday('now'),%Q,%Q,%Q)",
| > > | | | 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 |
** 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();
if( !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","");
db_begin_write();
chat_purge();
if( nByte==0 ){
if( zMsg[0] ){
db_multi_exec(
"INSERT INTO chat(mtime,lmtime,xfrom,xmsg)"
"VALUES(julianday('now'),%Q,%Q,%Q)",
P("lmtime"), zUserName, zMsg
);
}
}else{
Stmt q;
Blob b;
db_prepare(&q,
"INSERT INTO chat(mtime,lmtime,xfrom,xmsg,file,fname,fmime)"
"VALUES(julianday('now'),%Q,%Q,%Q,:file,%Q,%Q)",
P("lmtime"), zUserName, zMsg, PD("file:filename",""),
PD("file:mimetype","application/octet-stream"));
blob_init(&b, P("file"), nByte);
db_bind_blob(&q, ":file", &b);
db_step(&q);
db_finalize(&q);
blob_reset(&b);
}
|
| ︙ | ︙ | |||
598 599 600 601 602 603 604 |
blob_append(&json, ",\n", 2);
}
blob_appendf(&json, "{\"msgid\":%d,", id);
blob_appendf(&json, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
if( zLMtime && zLMtime[0] ){
blob_appendf(&json, "\"lmtime\":%!j,", zLMtime);
}
| > > > > > | > | > | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
blob_append(&json, ",\n", 2);
}
blob_appendf(&json, "{\"msgid\":%d,", id);
blob_appendf(&json, "\"mtime\":\"%.10sT%sZ\",", zDate, zDate+11);
if( zLMtime && zLMtime[0] ){
blob_appendf(&json, "\"lmtime\":%!j,", zLMtime);
}
blob_append(&json, "\"xfrom\":", -1);
if(zFrom){
blob_appendf(&json, "%!j,", zFrom);
}else{
/* see https://fossil-scm.org/forum/forumpost/e0be0eeb4c */
blob_appendf(&json, "null,");
}
blob_appendf(&json, "\"uclr\":%!j,",
user_color(zFrom ? zFrom : "nobody"));
zMsg = chat_format_to_html(zRawMsg ? zRawMsg : "");
blob_appendf(&json, "\"xmsg\":%!j,", zMsg);
fossil_free(zMsg);
if( nByte==0 ){
blob_appendf(&json, "\"fsize\":0");
|
| ︙ | ︙ |
Changes to src/chat.js.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
| | < < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
messagesWrapper: E1('#chat-messages-wrapper'),
inputForm: E1('#chat-form'),
btnSubmit: E1('#chat-message-submit'),
inputSingle: E1('#chat-input-single'),
inputMulti: E1('#chat-input-multi'),
inputCurrent: undefined/*one of inputSingle or inputMulti*/,
inputFile: E1('#chat-input-file'),
contentDiv: E1('div.content')
},
me: F.user.name,
mxMsg: F.config.chat.initSize ? -F.config.chat.initSize : -50,
mnMsg: undefined/*lowest message ID we've seen so far (for history loading)*/,
pageIsActive: 'visible'===document.visibilityState,
changesSincePageHidden: 0,
notificationBubbleColor: 'white',
|
| ︙ | ︙ | |||
226 227 228 229 230 231 232 |
'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
);
}else{
eMsg.scrollIntoView(false);
}
return this;
},
| | | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false)
);
}else{
eMsg.scrollIntoView(false);
}
return this;
},
/* Injects element e as a new row in the chat, at the oldest end
of the list if atEnd is truthy, else at the newest end of the
list. */
injectMessageElem: function f(e, atEnd){
const mip = atEnd ? this.e.loadOlderToolbar : this.e.messageInjectPoint,
holder = this.e.messagesWrapper,
prevMessage = this.e.newestMessage;
if(atEnd){
const fe = mip.nextElementSibling;
if(fe) mip.parentNode.insertBefore(e, fe);
|
| ︙ | ︙ | |||
337 338 339 340 341 342 343 |
}else if(Chat.e.newestMessage){
Chat.e.newestMessage.scrollIntoView(false);
}
},
toggleChatOnlyMode: function(){
return this.chatOnlyMode(!this.isChatOnlyMode());
},
| < < < < < < < < | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
}else if(Chat.e.newestMessage){
Chat.e.newestMessage.scrollIntoView(false);
}
},
toggleChatOnlyMode: function(){
return this.chatOnlyMode(!this.isChatOnlyMode());
},
messageIsInView: function(e){
return e ? overlapsElemView(e, this.e.messagesWrapper) : false;
},
settings:{
get: (k,dflt)=>F.storage.get(k,dflt),
getBool: (k,dflt)=>F.storage.getBool(k,dflt),
set: (k,v)=>F.storage.set(k,v),
|
| ︙ | ︙ | |||
386 387 388 389 390 391 392 |
}
return this;
},
/**
Sets the current new-message audio alert URI (must be a
repository-relative path which responds with an audio
file). Pass a falsy value to disable audio alerts. Returns
| | | 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
}
return this;
},
/**
Sets the current new-message audio alert URI (must be a
repository-relative path which responds with an audio
file). Pass a falsy value to disable audio alerts. Returns
this.
*/
setNewMessageSound: function f(uri){
delete this.playNewMessageSound.audio;
this.playNewMessageSound.uri = uri;
this.settings.set('audible-alert', !!uri);
return this;
}
|
| ︙ | ︙ | |||
417 418 419 420 421 422 423 |
}
if(cs.settings.getBool('monospace-messages',false)){
document.body.classList.add('monospace-messages');
}
cs.inputMultilineMode(cs.settings.getBool('edit-multiline',false));
cs.chatOnlyMode(cs.settings.getBool('chat-only-mode'));
cs.pageTitleOrig = cs.e.pageTitle.innerText;
| < | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
}
if(cs.settings.getBool('monospace-messages',false)){
document.body.classList.add('monospace-messages');
}
cs.inputMultilineMode(cs.settings.getBool('edit-multiline',false));
cs.chatOnlyMode(cs.settings.getBool('chat-only-mode'));
cs.pageTitleOrig = cs.e.pageTitle.innerText;
const qs = (e)=>document.querySelector(e);
const argsToArray = function(args){
return Array.prototype.slice.call(args,0);
};
/**
Reports an error via console.error() and as a toast message.
Accepts any argument types valid for fossil.toast.error().
|
| ︙ | ︙ | |||
441 442 443 444 445 446 447 |
using fossil.dom.append(), so may be of any type supported by
that function.
*/
cs.reportErrorAsMessage = function(/*msg args*/){
const args = argsToArray(arguments);
console.error("chat error:",args);
const d = new Date().toISOString(),
| | | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
using fossil.dom.append(), so may be of any type supported by
that function.
*/
cs.reportErrorAsMessage = function(/*msg args*/){
const args = argsToArray(arguments);
console.error("chat error:",args);
const d = new Date().toISOString(),
mw = new this.MessageWidget({
isError: true,
xfrom: null,
msgid: -1,
mtime: d,
lmtime: d,
xmsg: args
});
this.injectMessageElem(mw.e.body);
mw.scrollIntoView();
};
cs.getMessageElemById = function(id){
return qs('[data-msgid="'+id+'"]');
};
|
| ︙ | ︙ | |||
612 613 614 615 616 617 618 |
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
' ',pad2(d.getHours()),':',pad2(d.getMinutes()),
':',pad2(d.getSeconds())
].join('');
};
cf.prototype = {
| < < < > > | | | 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 |
d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/),
'-',pad2(d.getDate()),
' ',pad2(d.getHours()),':',pad2(d.getMinutes()),
':',pad2(d.getSeconds())
].join('');
};
cf.prototype = {
scrollIntoView: function(){
this.e.content.scrollIntoView();
},
setMessage: function(m){
const ds = this.e.body.dataset;
ds.timestamp = m.mtime;
ds.lmtime = m.lmtime;
ds.msgid = m.msgid;
ds.xfrom = m.xfrom || '';
if(m.xfrom === Chat.me){
D.addClass(this.e.body, 'mine');
}
if(m.uclr){
this.e.content.style.backgroundColor = m.uclr;
this.e.tab.style.backgroundColor = m.uclr;
}
const d = new Date(m.mtime);
D.clearElement(this.e.tab);
var contentTarget = this.e.content;
var eXFrom /* element holding xfrom name */;
if(m.xfrom){
eXFrom = D.append(D.addClass(D.span(), 'xfrom'), m.xfrom);
D.append(
this.e.tab, eXFrom,
D.text(" #",(m.msgid||'???'),' @ ',theTime(d))
);
}else{/*notification*/
D.addClass(this.e.body, 'notification');
if(m.isError){
D.addClass([contentTarget, this.e.tab], 'error');
}
D.append(
|
| ︙ | ︙ | |||
691 692 693 694 695 696 697 698 699 700 701 702 703 704 |
// Used by Chat.reportErrorAsMessage()
D.append(contentTarget, m.xmsg);
}else{
contentTarget.innerHTML = m.xmsg;
}
}
this.e.tab.addEventListener('click', this._handleLegendClicked, false);
return this;
},
/* Event handler for clicking .message-user elements to show their
timestamps. */
_handleLegendClicked: function f(ev){
if(!f.popup){
/* Timestamp popup widget */
| > > > | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 |
// Used by Chat.reportErrorAsMessage()
D.append(contentTarget, m.xmsg);
}else{
contentTarget.innerHTML = m.xmsg;
}
}
this.e.tab.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
timestamps. */
_handleLegendClicked: function f(ev){
if(!f.popup){
/* Timestamp popup widget */
|
| ︙ | ︙ | |||
963 964 965 966 967 968 969 |
},{
label: "Images inline",
boolValue: ()=>Chat.settings.getBool('images-inline'),
callback: function(){
const v = Chat.settings.toggle('images-inline');
F.toast.message("Image mode set to "+(v ? "inline" : "hyperlink")+".");
}
| < < < < | 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
},{
label: "Images inline",
boolValue: ()=>Chat.settings.getBool('images-inline'),
callback: function(){
const v = Chat.settings.toggle('images-inline');
F.toast.message("Image mode set to "+(v ? "inline" : "hyperlink")+".");
}
}];
/** Set up selection list of notification sounds. */
if(true/*flip this to false to enable selection of audio files*/){
settingsOps.push({
label: "Audible alerts",
boolValue: ()=>Chat.settings.getBool('audible-alert'),
|
| ︙ | ︙ | |||
1081 1082 1083 1084 1085 1086 1087 |
return rect.right - popupSize.width;
};
settingsPopup.options.adjustY = function(y){
const rect = settingsButton.getBoundingClientRect();
return rect.top - popupSize.height -2;
};
})()/*#chat-settings-button setup*/;
| < < < < < < < < < < < < < | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 |
return rect.right - popupSize.width;
};
settingsPopup.options.adjustY = function(y){
const rect = settingsButton.getBoundingClientRect();
return rect.top - popupSize.height -2;
};
})()/*#chat-settings-button setup*/;
/** Callback for poll() to inject new content into the page. jx ==
the response from /chat-poll. If atEnd is true, the message is
appended to the end of the chat list (for loading older
messages), else the beginning (the default). */
const newcontent = function f(jx,atEnd){
if(!f.processPost){
|
| ︙ | ︙ |
Changes to src/clone.c.
| ︙ | ︙ | |||
284 285 286 287 288 289 290 |
db_multi_exec("VACUUM");
db_protect_pop();
fossil_print("\nproject-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
| | < > | | | | | | < < < < < < > | | 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 |
db_multi_exec("VACUUM");
db_protect_pop();
fossil_print("\nproject-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
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);
blob_append(&cmd, " open ", -1);
blob_append_escaped_arg(&cmd, zRepo);
blob_append(&cmd, " --workdir ", -1);
blob_append_escaped_arg(&cmd, zWorkDir);
if( allowNested ){
blob_append(&cmd, " --nested", -1);
}
fossil_system(blob_str(&cmd));
blob_reset(&cmd);
}
}
/*
** If user chooses to use HTTP Authentication over unencrypted HTTP,
** remember decision. Otherwise, if the URL is being changed and no
** preference has been indicated, err on the safe side and revert the
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
454 455 456 457 458 459 460 |
if( db.nProtect<1 ){
fossil_panic("too many db_protect_pop() calls");
}
db.protectMask = db.aProtect[--db.nProtect];
}
/*
| | | | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
if( db.nProtect<1 ){
fossil_panic("too many db_protect_pop() calls");
}
db.protectMask = db.aProtect[--db.nProtect];
}
/*
** Verify that the desired database write protections are in place.
** Throw a fatal error if not.
*/
void db_assert_protected(unsigned flags){
if( (flags & db.protectMask)!=flags ){
fossil_fatal("missing database write protection bits: %02x",
flags & ~db.protectMask);
}
}
/*
** Assert that either all protections are off (including PROTECT_BASELINE
** which is usually always enabled), or the setting named in the argument
|
| ︙ | ︙ | |||
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 |
alert_find_emailaddr_func, 0, 0);
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
alert_display_name_func, 0, 0);
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
db_obscure, 0, 0);
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
static char *zSavedKey = 0;
| > > > | 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 |
alert_find_emailaddr_func, 0, 0);
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
alert_display_name_func, 0, 0);
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
db_obscure, 0, 0);
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
db_win_reserved_func,0,0
);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
static char *zSavedKey = 0;
|
| ︙ | ︙ | |||
1706 1707 1708 1709 1710 1711 1712 |
*/
int db_database_slot(const char *zLabel){
int iSlot = -1;
int rc;
Stmt q;
if( g.db==0 ) return iSlot;
rc = db_prepare_ignore_error(&q, "PRAGMA database_list");
| | | | | | > | 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 |
*/
int db_database_slot(const char *zLabel){
int iSlot = -1;
int rc;
Stmt q;
if( g.db==0 ) return iSlot;
rc = db_prepare_ignore_error(&q, "PRAGMA database_list");
if( rc==SQLITE_OK ){
while( db_step(&q)==SQLITE_ROW ){
if( fossil_strcmp(db_column_text(&q,1),zLabel)==0 ){
iSlot = db_column_int(&q, 0);
break;
}
}
}
db_finalize(&q);
return iSlot;
}
/*
|
| ︙ | ︙ | |||
1829 1830 1831 1832 1833 1834 1835 |
return mprintf("%s/fossil.db", zXdgHome);
}
/* The HOME variable is required in order to continue.
*/
if( zHome==0 ){
if( isOptional ) return 0;
| | | 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 |
return mprintf("%s/fossil.db", zXdgHome);
}
/* The HOME variable is required in order to continue.
*/
if( zHome==0 ){
if( isOptional ) return 0;
fossil_fatal("cannot locate home directory - please set one of the "
"FOSSIL_HOME, XDG_CONFIG_HOME, or HOME environment "
"variables");
}
/* Step 4: If $HOME/.config is a directory -> $HOME/.config/fossil.db
*/
zXdgHome = mprintf("%s/.config", zHome);
|
| ︙ | ︙ | |||
1879 1880 1881 1882 1883 1884 1885 |
if( file_isdir(zHome, ExtFILE)==0 ){
file_mkdir(zHome, ExtFILE, 0);
}
rc = file_access(zHome, W_OK);
fossil_free(zHome);
if( rc ){
if( isOptional ) return 0;
| | | | 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 |
if( file_isdir(zHome, ExtFILE)==0 ){
file_mkdir(zHome, ExtFILE, 0);
}
rc = file_access(zHome, W_OK);
fossil_free(zHome);
if( rc ){
if( isOptional ) return 0;
fossil_fatal("home directory \"%s\" must be writeable", zHome);
}
db_init_database(zDbName, zConfigSchema, (char*)0);
}
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");
g.dbConfig = 0;
}else{
g.dbConfig = db_open(zDbName);
db_set_main_schemaname(g.dbConfig, "configdb");
|
| ︙ | ︙ | |||
2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 |
}else{
assert( argc==3 );
assert( rc==0 || rc==1 );
if( sqlite3_value_type(argv[2-rc])==SQLITE_NULL ) rc = 1-rc;
sqlite3_result_value(context, argv[2-rc]);
}
}
/*
** Convert the input string into a artifact hash. Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
**
** The value returned is stored in static space and will be overwritten
| > > > > > > > > > > > > > > > > | 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 |
}else{
assert( argc==3 );
assert( rc==0 || rc==1 );
if( sqlite3_value_type(argv[2-rc])==SQLITE_NULL ) rc = 1-rc;
sqlite3_result_value(context, argv[2-rc]);
}
}
/*
** Implementation of the "win_reserved(X)" SQL function, a wrapper
** for file_is_win_reserved(X) which returns true if X is
** a Windows-reserved filename.
*/
LOCAL void db_win_reserved_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char * zName = (const char *)sqlite3_value_text(argv[0]);
if( zName!=0 ){
sqlite3_result_int(context, file_is_win_reserved(zName)!=0);
}
}
/*
** Convert the input string into a artifact hash. Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
**
** The value returned is stored in static space and will be overwritten
|
| ︙ | ︙ | |||
3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 |
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 */
url_proxy_options();
emptyFlag = find_option("empty",0,0)!=0;
keepFlag = find_option("keep",0,0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
allowNested = find_option("nested",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
| > | 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 |
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 */
url_proxy_options();
emptyFlag = find_option("empty",0,0)!=0;
keepFlag = find_option("keep",0,0)!=0;
forceMissingFlag = find_option("force-missing",0,0)!=0;
allowNested = find_option("nested",0,0)!=0;
setmtimeFlag = find_option("setmtime",0,0)!=0;
|
| ︙ | ︙ | |||
3513 3514 3515 3516 3517 3518 3519 |
fossil_fatal("cannot create directory %s", zWorkDir);
}
}
if( file_chdir(zWorkDir, 0) ){
fossil_fatal("unable to make %s the working directory", zWorkDir);
}
}
| | > > > > | 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 |
fossil_fatal("cannot create directory %s", zWorkDir);
}
}
if( file_chdir(zWorkDir, 0) ){
fossil_fatal("unable to make %s the working directory", zWorkDir);
}
}
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 or --force option to override", file_getcwd(0,0));
}
if( db_open_local_v2(0, allowNested) ){
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
}
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 |
margin: 0 0.25em 0em 0.15em;
padding: 0 0.5em 0.15em 0.5em;
cursor: pointer;
white-space: nowrap;
}
body.chat .fossil-tooltip.help-buttonlet-content {
font-size: 80%;
}
/* The popup element for displaying message timestamps
and deletion controls. */
body.chat .chat-message-popup {
font-family: monospace;
font-size: 0.8em;
text-align: left;
| > > > > > > | 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 |
margin: 0 0.25em 0em 0.15em;
padding: 0 0.5em 0.15em 0.5em;
cursor: pointer;
white-space: nowrap;
}
body.chat .fossil-tooltip.help-buttonlet-content {
font-size: 80%;
}
body.chat .message-widget .message-widget-tab .xfrom {
/* Element which holds the "this message is from user X" part
of the message banner. */
font-style: italic;
font-weight: bold;
}
/* The popup element for displaying message timestamps
and deletion controls. */
body.chat .chat-message-popup {
font-family: monospace;
font-size: 0.8em;
text-align: left;
|
| ︙ | ︙ | |||
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 |
max-width: 45%;
max-height: 45%;
}
input[type="checkbox"].diff-toggle {
float: right;
}
/* Objects in the "desktoponly" class are invisible on mobile */
@media screen and (max-width: 600px) {
.desktoponly {
display: none;
}
}
/* Objects in the "wideonly" class are invisible only on wide-screen desktops */
@media screen and (max-width: 1200px) {
.wideonly {
display: none;
}
}
| > > > > > > > > > > > > > > > > > > > > | 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 |
max-width: 45%;
max-height: 45%;
}
input[type="checkbox"].diff-toggle {
float: right;
}
body.branch .brlist > table > tbody > tr:hover:not(.selected),
body.branch .brlist > table > tbody > tr.selected {
background-color: #ffc;
}
body.branch .brlist > table > tbody td:first-child > input {
cursor: pointer;
}
body.branch .brlist > table > tbody > tr > td:nth-child(1) {
display: flex;
flex-direction: row;
justify-content: space-between;
}
body.branch .submenu > a.timeline-link {
display: none;
}
body.branch .submenu > a.timeline-link.selected {
display: inline;
}
/* Objects in the "desktoponly" class are invisible on mobile */
@media screen and (max-width: 600px) {
.desktoponly {
display: none;
}
}
/* Objects in the "wideonly" class are invisible only on wide-screen desktops */
@media screen and (max-width: 1200px) {
.wideonly {
display: none;
}
}
|
Changes to src/file.c.
| ︙ | ︙ | |||
384 385 386 387 388 389 390 |
**
** If a problem is found, print a warning message (using fossil_warning())
** and return non-zero. If everything is ok, return zero.
*/
int file_unsafe_in_tree_path(const char *zFile){
int n;
if( !file_is_absolute_path(zFile) ){
| | | | 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
**
** If a problem is found, print a warning message (using fossil_warning())
** and return non-zero. If everything is ok, return zero.
*/
int file_unsafe_in_tree_path(const char *zFile){
int n;
if( !file_is_absolute_path(zFile) ){
fossil_fatal("%s is not an absolute pathname",zFile);
}
if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
fossil_fatal("%s is not a prefix of %s", g.zLocalRoot, zFile);
}
n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
if( n ){
fossil_warning("cannot write to %s because non-directory object %.*s"
" is in the way", zFile, n, zFile);
}
return n;
|
| ︙ | ︙ | |||
1146 1147 1148 1149 1150 1151 1152 |
nBuf = sizeof(zTemp);
}
#ifdef _WIN32
win32_getcwd(zBuf, nBuf);
#else
if( getcwd(zBuf, nBuf-1)==0 ){
if( errno==ERANGE ){
| | | | 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
nBuf = sizeof(zTemp);
}
#ifdef _WIN32
win32_getcwd(zBuf, nBuf);
#else
if( getcwd(zBuf, nBuf-1)==0 ){
if( errno==ERANGE ){
fossil_fatal("pwd too big: max %d", nBuf-1);
}else{
fossil_fatal("cannot find current working directory; %s",
strerror(errno));
}
}
#endif
return zBuf==zTemp ? fossil_strdup(zBuf) : zBuf;
}
|
| ︙ | ︙ | |||
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 |
fossil_print(" file_isfile_or_link = %d\n", file_isfile_or_link(zPath));
fossil_print(" file_islink = %d\n", file_islink(zPath));
fossil_print(" file_isexe(RepoFILE) = %d\n", file_isexe(zPath,RepoFILE));
fossil_print(" file_isdir(RepoFILE) = %d\n", file_isdir(zPath,RepoFILE));
fossil_print(" file_is_repository = %d\n", file_is_repository(zPath));
fossil_print(" file_is_reserved_name = %d\n",
file_is_reserved_name(zFull,-1));
blob_reset(&x);
if( reset ) resetStat();
}
/*
** COMMAND: test-file-environment
**
| > | 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 |
fossil_print(" file_isfile_or_link = %d\n", file_isfile_or_link(zPath));
fossil_print(" file_islink = %d\n", file_islink(zPath));
fossil_print(" file_isexe(RepoFILE) = %d\n", file_isexe(zPath,RepoFILE));
fossil_print(" file_isdir(RepoFILE) = %d\n", file_isdir(zPath,RepoFILE));
fossil_print(" file_is_repository = %d\n", file_is_repository(zPath));
fossil_print(" file_is_reserved_name = %d\n",
file_is_reserved_name(zFull,-1));
fossil_print(" file_in_cwd = %d\n", file_in_cwd(zPath));
blob_reset(&x);
if( reset ) resetStat();
}
/*
** COMMAND: test-file-environment
**
|
| ︙ | ︙ | |||
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 |
for(i=2; i<g.argc; i++){
if( file_tree_name(g.argv[i], &x, absoluteFlag, 1) ){
fossil_print("%s\n", blob_buffer(&x));
blob_reset(&x);
}
}
}
/*
** Parse a URI into scheme, host, port, and path.
*/
void file_parse_uri(
const char *zUri,
Blob *pScheme,
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 |
for(i=2; i<g.argc; i++){
if( file_tree_name(g.argv[i], &x, absoluteFlag, 1) ){
fossil_print("%s\n", blob_buffer(&x));
blob_reset(&x);
}
}
}
/*
** zFile is the name of a file. Return true if that file is in the
** current working directory (the "pwd" or file_getcwd() directory).
** Return false if the file is someplace else.
*/
int file_in_cwd(const char *zFile){
char *zFull = file_canonical_name_dup(zFile);
char *zCwd = file_getcwd(0,0);
size_t nCwd = strlen(zCwd);
size_t nFull = strlen(zFull);
int rc = 1;
int (*xCmp)(const char*,const char*,int);
if( filenames_are_case_sensitive() ){
xCmp = fossil_strncmp;
}else{
xCmp = fossil_strnicmp;
}
if( nFull>nCwd+1
&& xCmp(zFull,zCwd,nCwd)==0
&& zFull[nCwd]=='/'
&& strchr(zFull+nCwd+1, '/')==0
){
rc = 1;
}else{
rc = 0;
}
fossil_free(zFull);
fossil_free(zCwd);
return rc;
}
/*
** Parse a URI into scheme, host, port, and path.
*/
void file_parse_uri(
const char *zUri,
Blob *pScheme,
|
| ︙ | ︙ | |||
1821 1822 1823 1824 1825 1826 1827 |
}
if( nBasis==0 ){
nBasis = 6;
zBasis = "fossil";
}
do{
blob_zero(pBuf);
| | | 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 |
}
if( nBasis==0 ){
nBasis = 6;
zBasis = "fossil";
}
do{
blob_zero(pBuf);
if( cnt++>20 ) fossil_fatal("cannot generate a temporary filename");
if( zTag==0 ){
sqlite3_randomness(15, zRand);
for(i=0; i<15; i++){
zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ];
}
zRand[15] = 0;
zTag = zRand;
|
| ︙ | ︙ | |||
2128 2129 2130 2131 2132 2133 2134 | #else while( z[0]=='/' && z[1]=='/' ) z++; #endif return z; } /* | | | | 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 |
#else
while( z[0]=='/' && z[1]=='/' ) z++;
#endif
return z;
}
/*
** Count the number of objects (files and subdirectories) in a given
** directory. Return the count. Return -1 if the object is not a
** directory.
*/
int file_directory_size(const char *zDir, const char *zGlob, int omitDotFiles){
void *zNative;
DIR *d;
int n = -1;
zNative = fossil_utf8_to_path(zDir,1);
|
| ︙ | ︙ |
Changes to src/finfo.c.
| ︙ | ︙ | |||
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 | ** Print the complete change history for a single file going backwards ** in time. The default mode is -l. ** ** For the -l|--log mode: If "-b|--brief" is specified one line per revision ** is printed, otherwise the full comment is printed. The "-n|--limit N" ** and "--offset P" options limits the output to the first N changes ** after skipping P changes. ** ** In the -s mode prints the status as <status> <revision>. This is ** a quick status and does not check for up-to-date-ness of the file. ** ** In the -p mode, there's an optional flag "-r|--revision REVISION". ** The specified version (or the latest checked out version) is printed ** to stdout. The -p mode is another form of the "cat" command. ** ** Options: ** -b|--brief Display a brief (one line / revision) summary ** --case-sensitive B Enable or disable case-sensitive filenames. B is a ** boolean: "yes", "no", "true", "false", etc. ** -l|--log Select log mode (the default) ** -n|--limit N Display the first N changes (default unlimited). ** N less than 0 means no limit. ** --offset P Skip P changes ** -p|--print Select print mode ** -r|--revision R Print the given revision (or ckout, if none is given) ** to stdout (only in print mode) | > > > > | 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 | ** Print the complete change history for a single file going backwards ** in time. The default mode is -l. ** ** For the -l|--log mode: If "-b|--brief" is specified one line per revision ** is printed, otherwise the full comment is printed. The "-n|--limit N" ** and "--offset P" options limits the output to the first N changes ** after skipping P changes. ** ** The -i mode will print the artifact ID of FILENAME given the REVISION ** provided by the -r flag (which is required). ** ** In the -s mode prints the status as <status> <revision>. This is ** a quick status and does not check for up-to-date-ness of the file. ** ** In the -p mode, there's an optional flag "-r|--revision REVISION". ** The specified version (or the latest checked out version) is printed ** to stdout. The -p mode is another form of the "cat" command. ** ** Options: ** -b|--brief Display a brief (one line / revision) summary ** --case-sensitive B Enable or disable case-sensitive filenames. B is a ** boolean: "yes", "no", "true", "false", etc. ** -i|--id Print the artifact ID (requires -r) ** -l|--log Select log mode (the default) ** -n|--limit N Display the first N changes (default unlimited). ** N less than 0 means no limit. ** --offset P Skip P changes ** -p|--print Select print mode ** -r|--revision R Print the given revision (or ckout, if none is given) ** to stdout (only in print mode) |
| ︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
if( rid==0 ){
fossil_fatal("no history for file: %b", &fname);
}
content_get(rid, &record);
}
blob_write_to_file(&record, "-");
blob_reset(&record);
blob_reset(&fname);
}else{
Blob line;
Stmt q;
Blob fname;
int rid;
const char *zFilename;
| > > > > > > > > > > > > > > > > > > > | 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 |
if( rid==0 ){
fossil_fatal("no history for file: %b", &fname);
}
content_get(rid, &record);
}
blob_write_to_file(&record, "-");
blob_reset(&record);
blob_reset(&fname);
}else if( find_option("id","i",0) ){
Blob fname;
const char *zRevision = find_option("revision", "r", 1);
verify_all_options();
if( zRevision==0 ) usage("-i|--id also requires -r|--revision");
if( g.argc!=3 ) usage("-r|--revision REVISION FILENAME");
file_tree_name(g.argv[2], &fname, 0, 1);
int rid = db_int(0, "SELECT rid FROM blob WHERE uuid ="
" (SELECT uuid FROM files_of_checkin(%Q)"
" WHERE filename=%B %s)",
zRevision, &fname, filename_collation());
if( rid==0 ) {
fossil_fatal("file not found for revision %s: %s",
zRevision, blob_str(&fname));
}
whatis_rid(rid,0);
blob_reset(&fname);
}else{
Blob line;
Stmt q;
Blob fname;
int rid;
const char *zFilename;
|
| ︙ | ︙ | |||
656 657 658 659 660 661 662 |
hyperlink_to_version(zCkin);
}
}
@ %W(zCom)</span>
if( (tmFlags & TIMELINE_COMPACT)!=0 ){
@ <span class='timelineEllipsis' data-id='%d(frid)' \
@ id='ellipsis-%d(frid)'>...</span>
| < | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
hyperlink_to_version(zCkin);
}
}
@ %W(zCom)</span>
if( (tmFlags & TIMELINE_COMPACT)!=0 ){
@ <span class='timelineEllipsis' data-id='%d(frid)' \
@ id='ellipsis-%d(frid)'>...</span>
}
if( tmFlags & TIMELINE_COLUMNAR ){
if( zBgClr && zBgClr[0] ){
@ <td class="timelineDetailCell" id='md%d(gidx)'>
}else{
@ <td class="timelineDetailCell">
}
|
| ︙ | ︙ |
Changes to src/forum.c.
| ︙ | ︙ | |||
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
** If the input login is found in the USER table, then check the USER.INFO
** field to see if it has display-name followed by an email address.
** If it does, that becomes the new display name. If not, let the display
** name just be the login.
**
** Space to hold the returned name is obtained from fossil_strdup() or
** mprintf() and should be freed by the caller.
*/
static char *display_name_from_login(const char *zLogin){
static Stmt q;
char *zResult;
db_static_prepare(&q,
"SELECT display_name(info) FROM user WHERE login=$login"
);
db_bind_text(&q, "$login", zLogin);
if( db_step(&q)==SQLITE_ROW && db_column_type(&q,0)==SQLITE_TEXT ){
const char *zDisplay = db_column_text(&q,0);
if( fossil_strcmp(zDisplay,zLogin)==0 ){
| > > > | > | > | > > > > | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
** If the input login is found in the USER table, then check the USER.INFO
** field to see if it has display-name followed by an email address.
** If it does, that becomes the new display name. If not, let the display
** name just be the login.
**
** Space to hold the returned name is obtained from fossil_strdup() or
** mprintf() and should be freed by the caller.
**
** HTML markup within the reply has been property escaped. Hyperlinks
** may have been added. The result is safe for use with %s.
*/
static char *display_name_from_login(const char *zLogin){
static Stmt q;
char *zResult;
db_static_prepare(&q,
"SELECT display_name(info) FROM user WHERE login=$login"
);
db_bind_text(&q, "$login", zLogin);
if( db_step(&q)==SQLITE_ROW && db_column_type(&q,0)==SQLITE_TEXT ){
const char *zDisplay = db_column_text(&q,0);
if( fossil_strcmp(zDisplay,zLogin)==0 ){
zResult = mprintf("%z%h</a>",
href("%R/timeline?ss=v&y=f&vfx&u=%t",zLogin),zLogin);
}else{
zResult = mprintf("%s (%z%h</a>)", zDisplay,
href("%R/timeline?ss=v&y=f&vfx&u=%t",zLogin),zLogin);
}
}else{
zResult = mprintf("%z%h</a>",
href("%R/timeline?ss=v&y=f&vfx&u=%t",zLogin),zLogin);
}
db_reset(&q);
return zResult;
}
/*
** Compute and return the display name for a ForumPost. If
** pManifest is not NULL, then it is a Manifest object for the post.
** if pManifest is NULL, this routine has to fetch and parse the
** Manifest object for itself.
**
** Memory to hold the display name is attached to p->zDisplayName
** and will be freed together with the ForumPost object p when it
** is freed.
**
** The returned text has had all HTML markup escaped and is safe for
** use within %s.
*/
static char *forum_post_display_name(ForumPost *p, Manifest *pManifest){
Manifest *pToFree = 0;
if( p->zDisplayName ) return p->zDisplayName;
if( pManifest==0 ){
pManifest = pToFree = manifest_get(p->fpid, CFTYPE_FORUM, 0);
if( pManifest==0 ) return "(unknown)";
|
| ︙ | ︙ | |||
479 480 481 482 483 484 485 |
/* Begin emitting the header line. The forum of the title
** varies depending on whether:
** * The post is unedited
** * The post was last edited by the original author
** * The post was last edited by a different person
*/
if( p->pEditHead ){
| | > | | | | | 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 |
/* Begin emitting the header line. The forum of the title
** varies depending on whether:
** * The post is unedited
** * The post was last edited by the original author
** * The post was last edited by a different person
*/
if( p->pEditHead ){
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())",
p->pEditHead->rDate);
}else{
zPosterName = forum_post_display_name(p, pManifest);
zEditorName = zPosterName;
}
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", p->rDate);
if( p->pEditPrev ){
zPosterName = forum_post_display_name(p->pEditHead, 0);
zEditorName = forum_post_display_name(p, pManifest);
zHist = bHist ? "" : "&hist";
@ <h3 class='forumPostHdr'>(%d(p->sid)\
@ .%0*d(fossil_num_digits(p->nEdit))(p->rev)) \
if( fossil_strcmp(zPosterName, zEditorName)==0 ){
@ By %s(zPosterName) on %h(zDate) edited from \
@ %z(href("%R/forumpost/%S?%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
}else{
@ Originally by %s(zPosterName) \
@ with edits by %s(zEditorName) on %h(zDate) from \
@ %z(href("%R/forumpost/%S?%s%s",p->pEditPrev->zUuid,zQuery,zHist))\
@ %d(p->sid).%0*d(fossil_num_digits(p->nEdit))(p->pEditPrev->rev)</a>
}
}else{
zPosterName = forum_post_display_name(p, pManifest);
@ <h3 class='forumPostHdr'>(%d(p->sid)) \
@ By %s(zPosterName) on %h(zDate)
}
fossil_free(zDate);
/* If debugging is enabled, link to the artifact page. */
if( g.perm.Debug ){
@ <span class="debug">\
|
| ︙ | ︙ | |||
1287 1288 1289 1290 1291 1292 1293 |
style_header("Reply");
if( pRootPost->zThreadTitle ){
@ <h1>Thread: %h(pRootPost->zThreadTitle)</h1>
}
@ <h2>Replying To:</h2>
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", pPost->rDate);
zDisplayName = display_name_from_login(pPost->zUser);
| | | 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 |
style_header("Reply");
if( pRootPost->zThreadTitle ){
@ <h1>Thread: %h(pRootPost->zThreadTitle)</h1>
}
@ <h2>Replying To:</h2>
zDate = db_text(0, "SELECT datetime(%.17g,toLocal())", pPost->rDate);
zDisplayName = display_name_from_login(pPost->zUser);
@ <h3 class='forumPostHdr'>By %s(zDisplayName) on %h(zDate)</h3>
fossil_free(zDisplayName);
fossil_free(zDate);
forum_render(0, pPost->zMimetype, pPost->zWiki, "forumEdit", 1);
if( P("preview") && !whitespace_only(zContent) ){
@ <h2>Preview:</h2>
forum_render(0, zMimetype,zContent, "forumEdit", 1);
}
|
| ︙ | ︙ |
Changes to src/fossil.numbered-lines.js.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 |
}else{/* single query result */
tbl = tbl[0];
}
}
if(!tbl) return /* no matching elements */;
const F = window.fossil, D = F.dom;
const tdLn = tbl.querySelector('td.line-numbers');
| < | | > | < | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
}else{/* single query result */
tbl = tbl[0];
}
}
if(!tbl) return /* no matching elements */;
const F = window.fossil, D = F.dom;
const tdLn = tbl.querySelector('td.line-numbers');
const urlArgsRaw = (window.location.search||'?')
.replace(/&?\budc=[^&]*/,'') /* "update display prefs cookie" */
.replace(/&?\bln=[^&]*/,'') /* inbound line number/range */
.replace('?&','?');
var urlArgsDecoded = urlArgsRaw;
try{urlArgsDecoded = decodeURIComponent(urlArgsRaw);}
catch{}
const lineState = { urlArgs: urlArgsDecoded, start: 0, end: 0 };
const lineTip = new F.PopupWidget({
style: {
cursor: 'pointer'
},
refresh: function(){
const link = this.state.link;
D.clearElement(link);
|
| ︙ | ︙ |
Added src/fossil.page.brlist.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
/*
* This script adds multiselect facility for the list of branches.
*
* Some info on 'const':
* https://caniuse.com/const
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const#browser_compatibility
*
* According to MDN 'const' requires Android's WebView 37,
* which may not be available.
* For the time being, continueing without 'const' and 'indexOf'
* (but that may be reconsidered later).
*/
window.addEventListener( 'load', function() {
var submenu = document.querySelector("div.submenu");
var anchor = document.createElement("A");
var brlistDataObj = document.getElementById("brlist-data");
var brlistDataTxt = brlistDataObj.textContent || brlistDataObj.innerText;
var brlistData = JSON.parse(brlistDataTxt);
anchor.classList.add("label");
anchor.classList.add("timeline-link");
anchor.href = brlistData.timelineUrl;
var prefix = anchor.href.toString() + "?ms=brlist&t=";
submenu.insertBefore(anchor,submenu.childNodes[0]);
var amendAnchor = function( selected ){
if( selected.length == 0 ){
anchor.classList.remove('selected');
anchor.href = prefix;
return;
}
re = selected.join(",");
try{re = encodeURIComponent(re);}
catch{console.log("encodeURIComponent() failed for ",re);}
anchor.href = prefix + re;
anchor.innerHTML = "View " + selected.length +
( selected.length > 1 ? " branches" : " branch" );
anchor.classList.add('selected');
}
var onChange = function( event ){
var cbx = event.target;
var tr = cbx.parentElement.parentElement;
var tag = cbx.parentElement.children[0].innerText;
var re = anchor.href.substr(prefix.length);
try{re = decodeURIComponent(re);}
catch{console.log("decodeURIComponent() failed for ",re);}
var selected = ( re != "" ? re.split(",") : [] );
if( cbx.checked ){
selected.push(tag);
tr.classList.add('selected');
}
else {
tr.classList.remove('selected');
for( var i = selected.length; --i >= 0 ;)
if( selected[i] == tag )
selected.splice(i,1);
}
amendAnchor( selected );
}
var stags = []; /* initially selected tags, not used above */
document.querySelectorAll("div.brlist > table td:first-child > input")
.forEach( function( cbx ){
cbx.onchange = onChange;
cbx.disabled = false;
if( cbx.checked ){
stags.push(cbx.parentElement.children[0].innerText);
cbx.parentElement.parentElement.classList.add('selected');
}
});
amendAnchor( stags );
}); // window.addEventListener( 'load' ...
|
Changes to src/graph.js.
| ︙ | ︙ | |||
566 567 568 569 570 571 572 |
canvasDiv.className += " sel";
}else if( selRow==p ){
selRow = null;
this.className = this.className.replace(" sel", "");
canvasDiv.className = canvasDiv.className.replace(" sel", "");
}else{
if( tx.fileDiff ){
| | | > > > > > > > > > > > > > > > | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 |
canvasDiv.className += " sel";
}else if( selRow==p ){
selRow = null;
this.className = this.className.replace(" sel", "");
canvasDiv.className = canvasDiv.className.replace(" sel", "");
}else{
if( tx.fileDiff ){
location.href=tx.baseUrl + "/fdiff?v1="+selRow.h+"&v2="+p.h;
}else{
var href = tx.baseUrl + "/vdiff?from="+selRow.h+"&to="+p.h;
let params = (new URL(document.location)).searchParams;
if(params && typeof params === "object"){
/* When called from /timeline page, If chng=str was specified in the
** QueryString, specify glob=str on the /vdiff page */
let glob = params.get("chng");
if( !glob ){
/* When called from /vdiff page, keep the glob= QueryString if
** present. */
glob = params.get("glob");
}
if( glob ){
href += "&glob=" + glob;
}
}
location.href = href;
}
}
e.stopPropagation()
}
function dblclickOnNode(e){
var p = tx.rowinfo[parseInt(this.id.match(/\d+$/)[0], 10)-tx.iTopRow];
window.location.href = tx.baseUrl+"/info/"+p.h
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
114 115 116 117 118 119 120 |
if( zCaSetting==0 || zCaSetting[0]=='\0' ){
/* CA location not specified, use platform's default certificate store */
X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
}else{
/* User has specified a CA location, make sure it exists and use it */
switch( file_isdir(zCaSetting, ExtFILE) ){
case 0: { /* doesn't exist */
| | | | | 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 |
if( zCaSetting==0 || zCaSetting[0]=='\0' ){
/* CA location not specified, use platform's default certificate store */
X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx));
}else{
/* User has specified a CA location, make sure it exists and use it */
switch( file_isdir(zCaSetting, ExtFILE) ){
case 0: { /* doesn't exist */
fossil_fatal("ssl-ca-location is set to '%s', "
"but is not a file or directory", zCaSetting);
break;
}
case 1: { /* directory */
zCaDirectory = zCaSetting;
break;
}
case 2: { /* file */
zCaFile = zCaSetting;
break;
}
}
if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){
fossil_fatal("Failed to use CA root certificates from "
"ssl-ca-location '%s'", zCaSetting);
}
}
/* Load client SSL identity, preferring the filename specified on the
** command line */
if( g.zSSLIdentity!=0 ){
identityFile = g.zSSLIdentity;
}else{
identityFile = db_get("ssl-identity", 0);
}
if( identityFile!=0 && identityFile[0]!='\0' ){
if( SSL_CTX_use_certificate_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
|| SSL_CTX_use_PrivateKey_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1
){
fossil_fatal("Could not load SSL identity from %s", identityFile);
}
}
/* Register a callback to tell the user what to do when the server asks
** for a cert */
SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
sslIsInit = 1;
|
| ︙ | ︙ |
Changes to src/http_transport.c.
| ︙ | ︙ | |||
125 126 127 128 129 130 131 |
zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
blob_append_escaped_arg(&zCmd, zHost);
fossil_free(zHost);
}else{
blob_append_escaped_arg(&zCmd, pUrlData->name);
}
if( !is_safe_fossil_command(pUrlData->fossil) ){
| | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
blob_append_escaped_arg(&zCmd, zHost);
fossil_free(zHost);
}else{
blob_append_escaped_arg(&zCmd, pUrlData->name);
}
if( !is_safe_fossil_command(pUrlData->fossil) ){
fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
"the server.", pUrlData->fossil);
}
blob_append_escaped_arg(&zCmd, pUrlData->fossil);
blob_append(&zCmd, " test-http", 10);
if( pUrlData->path && pUrlData->path[0] ){
blob_append_escaped_arg(&zCmd, pUrlData->path);
}else{
fossil_fatal("ssh:// URI does not specify a path to the repository");
}
if( g.fSshTrace ){
fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
}
popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0);
if( sshPid==0 ){
socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
|
| ︙ | ︙ | |||
179 180 181 182 183 184 185 |
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 ){
| | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
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 ){
fossil_fatal("cannot output temporary file: %s", transport.zOutFile);
}
transport.isOpen = 1;
}else{
rc = socket_open(pUrlData);
if( rc==0 ) transport.isOpen = 1;
}
}
|
| ︙ | ︙ |
Changes to src/import.c.
| ︙ | ︙ | |||
634 635 636 637 638 639 640 |
fossil_free(gg.aData); gg.aData = 0;
gg.nData = atoi(&zLine[5]);
if( gg.nData ){
int got;
gg.aData = fossil_malloc( gg.nData+1 );
got = fread(gg.aData, 1, gg.nData, pIn);
if( got!=gg.nData ){
| | | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
fossil_free(gg.aData); gg.aData = 0;
gg.nData = atoi(&zLine[5]);
if( gg.nData ){
int got;
gg.aData = fossil_malloc( gg.nData+1 );
got = fread(gg.aData, 1, gg.nData, pIn);
if( got!=gg.nData ){
fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
}
gg.aData[got] = '\0';
if( gg.zComment==0 &&
(gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
/* Strip trailing newline, it's appended to the comment. */
if( gg.aData[got-1] == '\n' )
gg.aData[got-1] = '\0';
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
*/
void ci_tags_page(void){
const char *zHash;
int rid;
Stmt q;
int cnt = 0;
Blob sql;
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(g.argv[2])
style_finish_page();
return;
}
zHash = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
style_header("Tags and Properties");
| > > > | | 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 |
*/
void ci_tags_page(void){
const char *zHash;
int rid;
Stmt q;
int cnt = 0;
Blob sql;
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(g.argv[2])
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";
@ <h1>Tags and Properties for %s(zType) \
@ %z(href("%R/ci/%!S",zHash))%S(zHash)</a></h1>
db_prepare(&q,
"SELECT tag.tagid, tagname, "
" (SELECT uuid FROM blob WHERE rid=tagxref.srcid AND rid!=%d),"
" value, datetime(tagxref.mtime,toLocal()), tagtype,"
" (SELECT uuid FROM blob WHERE rid=tagxref.origid AND rid!=%d)"
" FROM tagxref JOIN tag ON tagxref.tagid=tag.tagid"
|
| ︙ | ︙ |
Changes to src/json_status.c.
| ︙ | ︙ | |||
165 166 167 168 169 170 171 |
case -4: zLabel = "INTEGRATE "; break;
}
blob_append(report, zPrefix, nPrefix);
blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0));
}
db_finalize(&q);
if( nErr ){
| | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
case -4: zLabel = "INTEGRATE "; break;
}
blob_append(report, zPrefix, nPrefix);
blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0));
}
db_finalize(&q);
if( nErr ){
fossil_fatal("aborting due to prior errors");
}
#endif
return cson_object_value( oPay );
}
#endif /* FOSSIL_ENABLE_JSON */
|
Changes to src/json_wiki.c.
| ︙ | ︙ | |||
458 459 460 461 462 463 464 |
json_set_err(FSL_JSON_E_DENIED,
"Requires 'j' or 'o' permissions.");
return NULL;
}
blob_append(&sql,"SELECT"
" DISTINCT substr(tagname,6) as name"
" FROM tag JOIN tagxref USING('tagid')"
| | > > | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
json_set_err(FSL_JSON_E_DENIED,
"Requires 'j' or 'o' permissions.");
return NULL;
}
blob_append(&sql,"SELECT"
" DISTINCT substr(tagname,6) as name"
" FROM tag JOIN tagxref USING('tagid')"
" WHERE tagname GLOB 'wiki-*'"
" AND TYPEOF(tagxref.value+0)='integer'",
/* ^^^ elide wiki- tags which are not wiki pages */
-1);
zGlob = json_find_option_cstr("glob",NULL,"g");
if(zGlob && *zGlob){
blob_append_sql(&sql," AND name %s GLOB %Q",
fInvert ? "NOT" : "", zGlob);
}else{
zGlob = json_find_option_cstr("like",NULL,"l");
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
168 169 170 171 172 173 174 |
** Make a record of a login attempt, if login record keeping is enabled.
*/
static void record_login_attempt(
const char *zUsername, /* Name of user logging in */
const char *zIpAddr, /* IP address from which they logged in */
int bSuccess /* True if the attempt was a success */
){
| | | | | | | | > > > > | 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 |
** Make a record of a login attempt, if login record keeping is enabled.
*/
static void record_login_attempt(
const char *zUsername, /* Name of user logging in */
const char *zIpAddr, /* IP address from which they logged in */
int bSuccess /* True if the attempt was a success */
){
if( db_get_boolean("access-log", 0) ){
create_accesslog_table();
db_multi_exec(
"INSERT INTO accesslog(uname,ipaddr,success,mtime)"
"VALUES(%Q,%Q,%d,julianday('now'));",
zUsername, zIpAddr, bSuccess
);
}
if( bSuccess ){
alert_user_contact(zUsername);
}
}
/*
** Searches for the user ID matching the given name and password.
** On success it returns a positive value. On error it returns 0.
** On serious (DB-level) error it will probably exit.
**
|
| ︙ | ︙ | |||
792 793 794 795 796 797 798 799 800 801 802 803 804 805 |
}
if( login_is_individual() ){
if( g.perm.EmailAlert && alert_enabled() ){
@ <hr>
@ <p>Configure <a href="%R/alerts">Email Alerts</a>
@ for user <b>%h(g.zLogin)</b></p>
}
if( g.perm.Password ){
char *zRPW = fossil_random_password(12);
@ <hr>
@ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
form_begin(0, "%R/login");
@ <table>
@ <tr><td class="form_label" id="oldpw">Old Password:</td>
| > > > > > | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
}
if( login_is_individual() ){
if( g.perm.EmailAlert && alert_enabled() ){
@ <hr>
@ <p>Configure <a href="%R/alerts">Email Alerts</a>
@ for user <b>%h(g.zLogin)</b></p>
}
if( db_table_exists("repository","forumpost") ){
@ <hr><p>
@ <a href="%R/timeline?ss=v&y=f&vfx&u=%t(g.zLogin)">Forum
@ post timeline</a> for user <b>%h(g.zLogin)</b></p>
}
if( g.perm.Password ){
char *zRPW = fossil_random_password(12);
@ <hr>
@ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
form_begin(0, "%R/login");
@ <table>
@ <tr><td class="form_label" id="oldpw">Old Password:</td>
|
| ︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 |
if( capability_has_any(pCap,"r") ) ssub[nsub++] = 't';
if( capability_has_any(pCap,"j") ) ssub[nsub++] = 'w';
ssub[nsub] = 0;
capability_free(pCap);
/* Also add the user to the subscriber table. */
zCode = db_text(0,
"INSERT INTO subscriber(semail,suname,"
| | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 |
if( capability_has_any(pCap,"r") ) ssub[nsub++] = 't';
if( capability_has_any(pCap,"j") ) ssub[nsub++] = 'w';
ssub[nsub] = 0;
capability_free(pCap);
/* Also add the user to the subscriber table. */
zCode = db_text(0,
"INSERT INTO subscriber(semail,suname,"
" sverified,sdonotcall,sdigest,ssub,sctime,mtime,smip,lastContact)"
" VALUES(%Q,%Q,%d,0,%d,%Q,now(),now(),%Q,now()/86400)"
" ON CONFLICT(semail) DO UPDATE"
" SET suname=excluded.suname"
" RETURNING hex(subscriberCode);",
/* semail */ zEAddr,
/* suname */ zUserID,
/* sverified */ 0,
/* sdigest */ 0,
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 |
if( file_chdir(zDir, 1) ){
fossil_panic("unable to chroot into %s", zDir);
}
g.fJail = 1;
zRepo = "/";
}else{
for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
| | | | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 |
if( file_chdir(zDir, 1) ){
fossil_panic("unable to chroot into %s", zDir);
}
g.fJail = 1;
zRepo = "/";
}else{
for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){}
if( zDir[i]!='/' ) fossil_fatal("bad repository name: %s", zRepo);
if( i>0 ){
zDir[i] = 0;
if( file_chdir(zDir, 1) ){
fossil_fatal("unable to chroot into %s", zDir);
}
zDir[i] = '/';
}
zRepo = &zDir[i];
}
}
if( stat(zRepo, &sStat)!=0 ){
|
| ︙ | ︙ |
Changes to src/main.mk.
| ︙ | ︙ | |||
224 225 226 227 228 229 230 231 232 233 234 235 236 237 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ | > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ |
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 |
int c;
c = fossil_strcmp(pA->zUuid, pB->zUuid);
if( c==0 ){
c = fossil_strcmp(pA->zName, pB->zName);
}
return c;
}
/*
** Scan artifact rid/pContent to see if it is a control artifact of
** any type:
**
** * Manifest
** * Control
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 |
int c;
c = fossil_strcmp(pA->zUuid, pB->zUuid);
if( c==0 ){
c = fossil_strcmp(pA->zName, pB->zName);
}
return c;
}
/*
** Inserts plink entries for FORUM, WIKI, and TECHNOTE manifests. May
** assert for other manifest types. If a parent entry exists, it also
** propagates any tags for that parent. This is a no-op if
** p->nParent==0.
*/
static void manifest_add_fwt_plink(int rid, Manifest *p){
int i;
int parentId = 0;
assert(p->type==CFTYPE_WIKI ||
p->type==CFTYPE_FORUM ||
p->type==CFTYPE_EVENT);
for(i=0; i<p->nParent; ++i){
int const pid = uuid_to_rid(p->azParent[i], 1);
if(0==i){
parentId = pid;
}
db_multi_exec(
"INSERT OR IGNORE INTO plink"
"(pid, cid, isprim, mtime, baseid)"
"VALUES(%d, %d, %d, %.17g, NULL)",
pid, rid, i==0, p->rDate);
}
if(parentId){
tag_propagate_all(parentId);
}
}
/*
** Scan artifact rid/pContent to see if it is a control artifact of
** any type:
**
** * Manifest
** * Control
|
| ︙ | ︙ | |||
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 |
tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
rid, p->rDate, tid);
}
}
if( parentid ){
tag_propagate_all(parentid);
}
}
if( p->type==CFTYPE_WIKI ){
char *zTag = mprintf("wiki-%s", p->zWikiTitle);
int prior = 0;
char cPrefix;
int nWiki;
char zLength[40];
| > > > > | 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 |
tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
rid, p->rDate, tid);
}
}
if( parentid ){
tag_propagate_all(parentid);
}
}
if(p->type==CFTYPE_WIKI || p->type==CFTYPE_FORUM
|| p->type==CFTYPE_EVENT){
manifest_add_fwt_plink(rid, p);
}
if( p->type==CFTYPE_WIKI ){
char *zTag = mprintf("wiki-%s", p->zWikiTitle);
int prior = 0;
char cPrefix;
int nWiki;
char zLength[40];
|
| ︙ | ︙ | |||
2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 |
);
fossil_free(zTitle);
}
if( p->zWiki[0] ){
backlink_extract(p->zWiki, p->zMimetype, rid, BKLNK_FORUM, p->rDate, 1);
}
}
db_end_transaction(0);
if( permitHooks ){
rc = xfer_run_common_script();
if( rc==TH_OK ){
rc = xfer_run_script(zScript, zUuid, 0);
}
}
| > | 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 |
);
fossil_free(zTitle);
}
if( p->zWiki[0] ){
backlink_extract(p->zWiki, p->zMimetype, rid, BKLNK_FORUM, p->rDate, 1);
}
}
db_end_transaction(0);
if( permitHooks ){
rc = xfer_run_common_script();
if( rc==TH_OK ){
rc = xfer_run_script(zScript, zUuid, 0);
}
}
|
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
133 134 135 136 137 138 139 | /* ** Add an entry to the FV table for all files renamed between ** version N and the version specified by vid. */ static void add_renames( const char *zFnCol, /* The FV column for the filename in vid */ | | | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
/*
** Add an entry to the FV table for all files renamed between
** version N and the version specified by vid.
*/
static void add_renames(
const char *zFnCol, /* The FV column for the filename in vid */
int vid, /* The desired version's checkin RID */
int nid, /* The checkin rid for the name pivot */
int revOK, /* OK to move backwards (child->parent) if true */
const char *zDebug /* Generate trace output if not NULL */
){
int nChng; /* Number of file name changes */
int *aChng; /* An array of file name changes */
int i; /* Loop counter */
find_filename_changes(nid, vid, revOK, &nChng, &aChng, zDebug);
|
| ︙ | ︙ | |||
172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
static void vmerge_insert(int id, int rid){
db_multi_exec(
"INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
"VALUES(%d,%d,(SELECT uuid FROM blob WHERE rid=%d))",
id, rid, rid
);
}
/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? ?VERSION?
**
** The argument VERSION is a version that should be merged into the
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
static void vmerge_insert(int id, int rid){
db_multi_exec(
"INSERT OR IGNORE INTO vmerge(id,merge,mhash)"
"VALUES(%d,%d,(SELECT uuid FROM blob WHERE rid=%d))",
id, rid, rid
);
}
/*
** Print the contents of the "fv" table on standard output, for debugging
** purposes.
**
** Only show entries where a file has changed, unless showAll is true.
*/
static void debug_fv_dump(int showAll){
Stmt q;
if( showAll ){
db_prepare(&q,
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, "
" isexe, islinkv, islinkm, fnn FROM fv"
);
}else{
db_prepare(&q,
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, "
" isexe, islinkv, islinkm, fnn FROM fv"
" WHERE chnged OR (ridv!=ridm AND ridm!=ridp)"
);
}
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d "
" islinkv=%d islinkm=%d\n",
db_column_int(&q, 0),
db_column_int(&q, 5),
db_column_int(&q, 6),
db_column_int(&q, 7),
db_column_int(&q, 4),
db_column_int(&q, 8),
db_column_int(&q, 9),
db_column_int(&q, 10));
fossil_print(" fn = [%s]\n", db_column_text(&q, 1));
fossil_print(" fnp = [%s]\n", db_column_text(&q, 2));
fossil_print(" fnm = [%s]\n", db_column_text(&q, 3));
fossil_print(" fnn = [%s]\n", db_column_text(&q, 11));
}
db_finalize(&q);
}
/*
** Print the content of the VFILE table on standard output, for
** debugging purposes.
*/
static void debug_show_vfile(void){
Stmt q;
int pvid = -1;
db_prepare(&q,
"SELECT vid, id, chnged, deleted, isexe, islink, rid, mrid, mtime,"
" pathname, origname, mhash FROM vfile"
" ORDER BY vid, pathname"
);
while( db_step(&q)==SQLITE_ROW ){
int vid = db_column_int(&q, 0);
int chnged = db_column_int(&q, 2);
int dltd = db_column_int(&q, 3);
int isexe = db_column_int(&q, 4);
int islnk = db_column_int(&q, 5);
int rid = db_column_int(&q, 6);
int mrid = db_column_int(&q, 7);
const char *zPath = db_column_text(&q, 9);
const char *zOrig = db_column_text(&q, 10);
if( vid!=pvid ){
fossil_print("VFILE vid=%d (%z):\n", vid,
db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid));
pvid = vid;
}
fossil_print(" rid %-6d mrid %-6d %4s %3s %3s %3s %s",
rid, mrid,
chnged ? "chng" : "",
dltd ? "del" : "",
isexe ? "exe" : "",
islnk ? "lnk" : "", zPath);
if( zOrig && zOrig[0] ){
fossil_print(" <- %s\n", zOrig);
}else{
fossil_print("\n");
}
}
db_finalize(&q);
}
/*
** COMMAND: test-show-vfile
** Usage: %fossil test-show-vfile
**
** Show the content of the VFILE table in a local check-out.
*/
void test_show_vfile_cmd(void){
if( g.argc!=2 ){
fossil_fatal("unknown arguments to the %s command\n", g.argv[1]);
}
verify_all_options();
db_must_be_within_tree();
debug_show_vfile();
}
/*
** COMMAND: merge
**
** Usage: %fossil merge ?OPTIONS? ?VERSION?
**
** The argument VERSION is a version that should be merged into the
|
| ︙ | ︙ | |||
246 247 248 249 250 251 252 253 254 255 256 257 258 259 | int backoutFlag; /* True if the --backout option is present */ int dryRunFlag; /* True if the --dry-run or -n option is present */ int forceFlag; /* True if the --force or -f option is present */ int forceMissingFlag; /* True if the --force-missing option is present */ const char *zBinGlob; /* The value of --binary */ const char *zPivot; /* The value of --baseline */ int debugFlag; /* True if --debug is present */ int keepMergeFlag; /* True if --keep-merge-files is present */ int nConflict = 0; /* Number of conflicts seen */ int nOverwrite = 0; /* Number of unmanaged files overwritten */ char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */ Stmt q; | > | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | int backoutFlag; /* True if the --backout option is present */ int dryRunFlag; /* True if the --dry-run or -n option is present */ int forceFlag; /* True if the --force or -f option is present */ int forceMissingFlag; /* True if the --force-missing option is present */ const char *zBinGlob; /* The value of --binary */ const char *zPivot; /* The value of --baseline */ int debugFlag; /* True if --debug is present */ int showVfileFlag; /* True if the --show-vfile flag is present */ int keepMergeFlag; /* True if --keep-merge-files is present */ int nConflict = 0; /* Number of conflicts seen */ int nOverwrite = 0; /* Number of unmanaged files overwritten */ char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */ Stmt q; |
| ︙ | ︙ | |||
270 271 272 273 274 275 276 |
forceMissingFlag = find_option("force-missing",0,0)!=0;
if( !verboseFlag ){
verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
}
pickFlag = find_option("cherrypick",0,0)!=0;
integrateFlag = find_option("integrate",0,0)!=0;
backoutFlag = find_option("backout",0,0)!=0;
| < > > > > > > > > > > > > > > > > > > > | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
forceMissingFlag = find_option("force-missing",0,0)!=0;
if( !verboseFlag ){
verboseFlag = find_option("detail",0,0)!=0; /* deprecated */
}
pickFlag = find_option("cherrypick",0,0)!=0;
integrateFlag = find_option("integrate",0,0)!=0;
backoutFlag = find_option("backout",0,0)!=0;
zBinGlob = find_option("binary",0,1);
dryRunFlag = find_option("dry-run","n",0)!=0;
if( !dryRunFlag ){
dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
}
forceFlag = find_option("force","f",0)!=0;
zPivot = find_option("baseline",0,1);
keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;
/* Undocumented --debug and --show-vfile options:
**
** When included on the command-line, --debug causes lots of state
** information to be displayed. This option is undocumented as it
** might change or be eliminated in future releases.
**
** The --show-vfile flag does a dump of the VFILE table for reference.
**
** Hints:
** * Combine --debug and --verbose for still more output.
** * The --dry-run option is also useful in combination with --debug.
*/
debugFlag = find_option("debug",0,0)!=0;
if( debugFlag && verboseFlag ) debugFlag = 2;
showVfileFlag = find_option("show-vfile",0,0)!=0;
verify_all_options();
db_must_be_within_tree();
if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("nothing is checked out");
}
if( forceFlag==0 && leaf_is_closed(vid) ){
fossil_fatal("cannot merge into a closed leaf. Use --force to override");
}
if( !dryRunFlag ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
db_get_int("autosync-tries", 1), 1) ){
fossil_fatal("merge abandoned due to sync failure");
}
}
|
| ︙ | ︙ | |||
439 440 441 442 443 444 445 |
"SELECT 1 FROM ancestor WHERE id=%d LIMIT 1",
vid, nid, pid, pid
) ? 'p' : 'n';
}
if( debugFlag ){
char *z;
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid);
| | | | | > > | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | > > | < < < < | < < < < | < < < < < < < < < < < < < < < < < < | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 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 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 |
"SELECT 1 FROM ancestor WHERE id=%d LIMIT 1",
vid, nid, pid, pid
) ? 'p' : 'n';
}
if( debugFlag ){
char *z;
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid);
fossil_print("N=%-4d %z (file rename pivot)\n", nid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
fossil_print("P=%-4d %z (file content pivot)\n", pid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
fossil_print("M=%-4d %z (merged-in version)\n", mid, z);
z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
fossil_print("V=%-4d %z (current version)\n", vid, z);
fossil_print("vAncestor = '%c'\n", vAncestor);
}
if( showVfileFlag ) debug_show_vfile();
/*
** The vfile.pathname field is used to match files against each other. The
** FV table contains one row for each each unique filename in
** in the current checkout, the pivot, and the version being merged.
*/
db_multi_exec(
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv(\n"
" fn TEXT UNIQUE %s,\n" /* The filename */
" idv INTEGER DEFAULT 0,\n" /* VFILE entry for current version */
" idp INTEGER DEFAULT 0,\n" /* VFILE entry for the pivot */
" idm INTEGER DEFAULT 0,\n" /* VFILE entry for version merging in */
" chnged BOOLEAN,\n" /* True if current version has been edited */
" ridv INTEGER DEFAULT 0,\n" /* Record ID for current version */
" ridp INTEGER DEFAULT 0,\n" /* Record ID for pivot */
" ridm INTEGER DEFAULT 0,\n" /* Record ID for merge */
" isexe BOOLEAN,\n" /* Execute permission enabled */
" fnp TEXT UNIQUE %s,\n" /* The filename in the pivot */
" fnm TEXT UNIQUE %s,\n" /* The filename in the merged version */
" fnn TEXT UNIQUE %s,\n" /* The filename in the name pivot */
" islinkv BOOLEAN,\n" /* True if current version is a symlink */
" islinkm BOOLEAN\n" /* True if merged version in is a symlink */
");",
filename_collation(), filename_collation(), filename_collation(),
filename_collation()
);
/*
** Compute name changes from N to V, P, and M
*/
add_renames("fn", vid, nid, 0, debugFlag ? "N->V" : 0);
add_renames("fnp", pid, nid, 0, debugFlag ? "N->P" : 0);
add_renames("fnm", mid, nid, backoutFlag, debugFlag ? "N->M" : 0);
if( debugFlag ){
fossil_print("******** FV after name change search *******\n");
debug_fv_dump(1);
}
if( nid!=pid ){
/* See forum thread https://fossil-scm.org/forum/forumpost/549700437b
**
** If a filename changes between nid and one of the other check-ins
** pid, vid, or mid, then it might not have changed for all of them.
** try to fill in the appropriate filename in all slots where the
** name is missing.
**
** This does not work if
** (1) The filename changes more than once in between nid and vid/mid
** (2) Two or more filenames swap places - for example if A is renamed
** to B and B is renamed to A.
** The Fossil merge algorithm breaks down in those cases. It will need
** to be completely rewritten to handle such complex cases. Such cases
** appear to be rare, and also confusing to humans.
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fnp=vfile.pathname FROM vfile"
" WHERE fnp IS NULL"
" AND vfile.pathname = fv.fnn"
" AND vfile.vid=%d;",
pid
);
db_multi_exec(
"UPDATE OR IGNORE fv SET fn=vfile.pathname FROM vfile"
" WHERE fn IS NULL"
" AND vfile.pathname = coalesce(fv.fnp,fv.fnn)"
" AND vfile.vid=%d;",
vid
);
db_multi_exec(
"UPDATE OR IGNORE fv SET fnm=vfile.pathname FROM vfile"
" WHERE fnm IS NULL"
" AND vfile.pathname = coalesce(fv.fnp,fv.fnn)"
" AND vfile.vid=%d;",
mid
);
db_multi_exec(
"UPDATE OR IGNORE fv SET fnp=vfile.pathname FROM vfile"
" WHERE fnp IS NULL"
" AND vfile.pathname IN (fv.fnm,fv.fn)"
" AND vfile.vid=%d;",
pid
);
db_multi_exec(
"UPDATE OR IGNORE fv SET fn=vfile.pathname FROM vfile"
" WHERE fn IS NULL"
" AND vfile.pathname = fv.fnm"
" AND vfile.vid=%d;",
vid
);
db_multi_exec(
"UPDATE OR IGNORE fv SET fnm=vfile.pathname FROM vfile"
" WHERE fnm IS NULL"
" AND vfile.pathname = fv.fn"
" AND vfile.vid=%d;",
mid
);
}
if( debugFlag ){
fossil_print("******** FV after name change fill-in *******\n");
debug_fv_dump(1);
}
/*
** Add files found in V
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fn=coalesce(fn%c,fnn) WHERE fn IS NULL;"
"REPLACE INTO fv(fn,fnp,fnm,fnn,idv,ridv,islinkv,isexe,chnged)"
" SELECT pathname, fnp, fnm, fnn, id, rid, islink, vf.isexe, vf.chnged"
" FROM vfile vf"
" LEFT JOIN fv ON fn=coalesce(origname,pathname)"
" AND rid>0 AND vf.chnged NOT IN (3,5)"
" WHERE vid=%d;",
vAncestor, vid
);
if( debugFlag>=2 ){
fossil_print("******** FV after adding files in current version *******\n");
debug_fv_dump(1);
}
/*
** Add files found in P
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fnp=coalesce(fnn,"
" (SELECT coalesce(origname,pathname) FROM vfile WHERE id=idv))"
" WHERE fnp IS NULL;"
"INSERT OR IGNORE INTO fv(fnp)"
" SELECT coalesce(origname,pathname) FROM vfile WHERE vid=%d;",
pid
);
if( debugFlag>=2 ){
fossil_print("******** FV after adding pivot files *******\n");
debug_fv_dump(1);
}
/*
** Add files found in M
*/
db_multi_exec(
"UPDATE OR IGNORE fv SET fnm=fnp WHERE fnm IS NULL;"
"INSERT OR IGNORE INTO fv(fnm)"
" SELECT pathname FROM vfile WHERE vid=%d;",
mid
);
if( debugFlag>=2 ){
fossil_print("******** FV after adding merge-in files *******\n");
debug_fv_dump(1);
}
/*
** Compute the file version ids for P and M
*/
if( pid==vid ){
db_multi_exec(
"UPDATE fv SET idp=idv, ridp=ridv WHERE ridv>0 AND chnged NOT IN (3,5)"
);
}else{
db_multi_exec(
"UPDATE fv SET idp=coalesce(vfile.id,0), ridp=coalesce(vfile.rid,0)"
" FROM vfile"
" WHERE vfile.vid=%d AND fv.fnp=vfile.pathname",
pid
);
}
db_multi_exec(
"UPDATE fv SET"
" idm=coalesce(vfile.id,0),"
" ridm=coalesce(vfile.rid,0),"
" islinkm=coalesce(vfile.islink,0),"
" isexe=coalesce(vfile.isexe,fv.isexe)"
" FROM vfile"
" WHERE vid=%d AND fnm=pathname",
mid
);
/*
** Update the execute bit on files where it's changed from P->M but not P->V
*/
db_prepare(&q,
"SELECT idv, fn, fv.isexe FROM fv, vfile p, vfile v"
" WHERE p.id=idp AND v.id=idv AND fv.isexe!=p.isexe AND v.isexe=p.isexe"
|
| ︙ | ︙ | |||
588 589 590 591 592 593 594 |
char *zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
file_setexe(zFullPath, isExe);
free(zFullPath);
db_multi_exec("UPDATE vfile SET isexe=%d WHERE id=%d", isExe, idv);
}
}
db_finalize(&q);
| > > > | > > > > | | | 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 |
char *zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
file_setexe(zFullPath, isExe);
free(zFullPath);
db_multi_exec("UPDATE vfile SET isexe=%d WHERE id=%d", isExe, idv);
}
}
db_finalize(&q);
if( debugFlag ){
fossil_print("******** FV final *******\n");
debug_fv_dump( debugFlag>=2 );
}
/************************************************************************
** All of the information needed to do the merge is now contained in the
** FV table. Starting here, we begin to actually carry out the merge.
**
** First, find files in M and V but not in P and report conflicts.
** The file in M will be ignored. It will be treated as if it
** does not exist.
*/
db_prepare(&q,
"SELECT idm FROM fv WHERE idp=0 AND idv>0 AND idm>0"
);
while( db_step(&q)==SQLITE_ROW ){
|
| ︙ | ︙ | |||
687 688 689 690 691 692 693 |
if( rc>=0 ){
if( !dryRunFlag ){
blob_write_to_file(&r, zFullPath);
file_setexe(zFullPath, isExe);
}
db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
if( rc>0 ){
| | > | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 |
if( rc>=0 ){
if( !dryRunFlag ){
blob_write_to_file(&r, zFullPath);
file_setexe(zFullPath, isExe);
}
db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
if( rc>0 ){
fossil_print("***** %d merge conflict%s in %s\n",
rc, rc>1 ? "s" : "", zName);
nConflict++;
}
}else{
fossil_print("***** Cannot merge binary file %s\n", zName);
nConflict++;
}
blob_reset(&p);
|
| ︙ | ︙ | |||
808 809 810 811 812 813 814 |
*/
db_multi_exec(
"UPDATE vfile SET pathname=origname || ' (overwritten by rename)'"
" WHERE pathname IS NULL"
);
/*
| | | 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 |
*/
db_multi_exec(
"UPDATE vfile SET pathname=origname || ' (overwritten by rename)'"
" WHERE pathname IS NULL"
);
/*
** Insert into V any files that are not in V or P but are in M.
*/
db_prepare(&q,
"SELECT idm, fnm FROM fv"
" WHERE idp=0 AND idv=0 AND idm>0"
);
while( db_step(&q)==SQLITE_ROW ){
int idm = db_column_int(&q, 0);
|
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
735 736 737 738 739 740 741 742 743 744 745 746 747 748 |
rid = symbolic_name_to_rid(zName, "*");
if( rid<0 ){
cgi_redirectf("%R/ambiguous/%T?src=%t", zName, g.zPath);
rid = 0;
}
return rid;
}
/*
** Generate a description of artifact "rid"
*/
void whatis_rid(int rid, int verboseFlag){
Stmt q;
int cnt;
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 |
rid = symbolic_name_to_rid(zName, "*");
if( rid<0 ){
cgi_redirectf("%R/ambiguous/%T?src=%t", zName, g.zPath);
rid = 0;
}
return rid;
}
/*
** Given an RID of a structural artifact, which is assumed to be
** valid, this function returns one of the CFTYPE_xxx values
** describing the record type, or 0 if the RID does not refer to an
** artifact record (as determined by reading the event table).
**
** Note that this function never returns CFTYPE_ATTACHMENT or
** CFTYPE_CLUSTER because those are not used in the event table. Thus
** it cannot be used to distinguish those artifact types from
** non-artifact file content.
**
** Potential TODO: if the rid is not found in the timeline, try to
** match it to a client file and return a hypothetical new
** CFTYPE_OPAQUE or CFTYPE_NONARTIFACT if a match is found.
*/
int whatis_rid_type(int rid){
Stmt q = empty_Stmt;
int type = 0;
/* Check for entries on the timeline that reference this object */
db_prepare(&q,
"SELECT type FROM event WHERE objid=%d", rid);
if( db_step(&q)==SQLITE_ROW ){
switch( db_column_text(&q,0)[0] ){
case 'c': type = CFTYPE_MANIFEST; break;
case 'w': type = CFTYPE_WIKI; break;
case 'e': type = CFTYPE_EVENT; break;
case 'f': type = CFTYPE_FORUM; break;
case 't': type = CFTYPE_TICKET; break;
case 'g': type = CFTYPE_CONTROL; break;
default: break;
}
}
db_finalize(&q);
return type;
}
/*
** A proxy for whatis_rid_type() which returns a brief string (in
** static memory) describing the record type. Returns NULL if rid does
** not refer to an artifact record (as determined by reading the event
** table). The returned string is intended to be used in headers which
** can refer to different artifact types. It is not "definitive," in
** that it does not distinguish between closely-related types like
** wiki creation, edit, and removal.
*/
char const * whatis_rid_type_label(int rid){
char const * zType = 0;
switch( whatis_rid_type(rid) ){
case CFTYPE_MANIFEST: zType = "Check-in"; break;
case CFTYPE_WIKI: zType = "Wiki-edit"; break;
case CFTYPE_EVENT: zType = "Technote"; break;
case CFTYPE_FORUM: zType = "Forum-post"; break;
case CFTYPE_TICKET: zType = "Ticket-change"; break;
case CFTYPE_CONTROL: zType = "Tag-change"; break;
default: break;
}
return zType;
}
/*
** Generate a description of artifact "rid"
*/
void whatis_rid(int rid, int verboseFlag){
Stmt q;
int cnt;
|
| ︙ | ︙ | |||
769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
db_finalize(&q);
/* Report any symbolic tags on this artifact */
db_prepare(&q,
"SELECT substr(tagname,5)"
" FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
" WHERE tagxref.rid=%d"
" AND tagname GLOB 'sym-*'"
" ORDER BY 1",
rid
);
cnt = 0;
while( db_step(&q)==SQLITE_ROW ){
const char *zPrefix = cnt++ ? ", " : "tags: ";
| > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
db_finalize(&q);
/* Report any symbolic tags on this artifact */
db_prepare(&q,
"SELECT substr(tagname,5)"
" FROM tag JOIN tagxref ON tag.tagid=tagxref.tagid"
" WHERE tagxref.rid=%d"
" AND tagxref.tagtype<>0"
" AND tagname GLOB 'sym-*'"
" ORDER BY 1",
rid
);
cnt = 0;
while( db_step(&q)==SQLITE_ROW ){
const char *zPrefix = cnt++ ? ", " : "tags: ";
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 |
fossil_trace("%s\n", z);
}
return rc;
}
/*
** Print an error message, rollback all databases, and quit. These
| | | > | | | > > > > | > | 1130 1131 1132 1133 1134 1135 1136 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 |
fossil_trace("%s\n", z);
}
return rc;
}
/*
** Print an error message, rollback all databases, and quit. These
** routines never return and produce a non-zero process exit status.
**
** The main difference between fossil_fatal() and fossil_panic() is that
** fossil_panic() makes an entry in the error log whereas fossil_fatal()
** does not. On POSIX platforms, if there is not an error log, then both
** routines work similarly with respect to user-visible effects. Hence,
** the routines are interchangable for commands and only act differently
** when processing web pages. On the Windows platform, fossil_panic()
** also displays a pop-up stating that an error has occured and allowing
** just-in-time debugging to commence. On all platforms, fossil_panic()
** ends execution with a SIGABRT signal, bypassing atexit processing.
** This signal can also produce a core dump on POSIX platforms.
**
** Use fossil_fatal() for malformed inputs that should be reported back
** to the user, but which do not represent a configuration problem or bug.
**
** Use fossil_panic() for any kind of error that should be brought to the
** attention of the system administrator or Fossil developers. It should
** be avoided for ordinary usage, parameter, OOM and I/O errors.
*/
NORETURN void fossil_panic(const char *zFormat, ...){
va_list ap;
int rc = 1;
char z[1000];
static int once = 0;
|
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
395 396 397 398 399 400 401 |
db_prepare(&q,
"SELECT name FROM sqlite_schema /*scan*/"
" WHERE type='table'"
" AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
"'config','shun','private','reportfmt',"
"'concealed','accesslog','modreq',"
"'purgeevent','purgeitem','unversioned',"
| | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
db_prepare(&q,
"SELECT name FROM sqlite_schema /*scan*/"
" WHERE type='table'"
" AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
"'config','shun','private','reportfmt',"
"'concealed','accesslog','modreq',"
"'purgeevent','purgeitem','unversioned',"
"'subscriber','pending_alert','chat')"
" AND name NOT GLOB 'sqlite_*'"
" AND name NOT GLOB 'fx_*'"
);
while( db_step(&q)==SQLITE_ROW ){
blob_appendf(&sql, "DROP TABLE IF EXISTS \"%w\";\n", db_column_text(&q,0));
}
db_finalize(&q);
|
| ︙ | ︙ |
Changes to src/regexp.c.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | ** but without any warranty; without even the implied warranty of ** merchantability or fitness for a particular purpose. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
******************************************************************************
**
** This file was adapted from the ext/misc/regexp.c file in SQLite3. That
** file is in the public domain.
**
** See ../www/grep.md for details of the algorithm and RE dialect.
**
**
** The following regular expression syntax is supported:
**
** X* zero or more occurrences of X
** X+ one or more occurrences of X
** X? zero or one occurrences of X
** X{p,q} between p and q occurrences of X
** (X) match X
** X|Y X or Y
** ^X X occurring at the beginning of the string
** X$ X occurring at the end of the string
** . Match any single character
** \c Character c where c is one of \{}()[]|*+?.
** \c C-language escapes for c in afnrtv. ex: \t or \n
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
** \xXX Where XX is exactly 2 hex digits, unicode value XX
** [abc] Any single character from the set abc
** [^abc] Any single character not in the set abc
** [a-z] Any single character in the range a-z
** [^a-z] Any single character not in the range a-z
** \b Word boundary
** \w Word character. [A-Za-z0-9_]
** \W Non-word character
** \d Digit
** \D Non-digit
** \s Whitespace character
** \S Non-whitespace character
**
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
*/
#include "config.h"
#include "regexp.h"
/* The end-of-input character */
#define RE_EOF 0 /* End of input */
|
| ︙ | ︙ | |||
195 196 197 198 199 200 201 |
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ANY: {
| | | | | | 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 |
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ANY: {
if( c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
if( re_word_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTWORD: {
if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_DIGIT: {
if( re_digit_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTDIGIT: {
if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_SPACE: {
if( re_space_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTSPACE: {
if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_BOUNDARY: {
if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
break;
}
case RE_OP_ANYSTAR: {
|
| ︙ | ︙ | |||
244 245 246 247 248 249 250 |
re_add_state(pThis, x+pRe->aArg[x]);
break;
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_match_end;
}
| | > > > | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
re_add_state(pThis, x+pRe->aArg[x]);
break;
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_match_end;
}
case RE_OP_CC_EXC: {
if( c==0 ) break;
/* fall-through */
}
case 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;
|
| ︙ | ︙ | |||
620 621 622 623 624 625 626 | ** ".*" (if the input regex lacks an initial "^") and afterwards there are ** one or more matching characters, enter those matching characters into ** zInit[]. The re_match() routine can then search ahead in the input ** string looking for the initial match without having to run the whole ** regex engine over the string. Do not worry able trying to match ** unicode characters beyond plane 0 - those are very rare and this is ** just an optimization. */ | | | | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 |
** ".*" (if the input regex lacks an initial "^") and afterwards there are
** one or more matching characters, enter those matching characters into
** zInit[]. The re_match() routine can then search ahead in the input
** string looking for the initial match without having to run the whole
** regex engine over the string. Do not worry able trying to match
** unicode characters beyond plane 0 - those are very rare and this is
** just an optimization. */
if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
pRe->zInit[j++] = (unsigned char)x;
}else if( x<=0xfff ){
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
|
| ︙ | ︙ | |||
662 663 664 665 666 667 668 669 670 671 672 |
){
ReCompiled *pRe; /* Compiled regular expression */
const char *zPattern; /* The regular expression */
const unsigned char *zStr;/* String being searched */
const char *zErr; /* Compile error message */
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
pRe = sqlite3_get_auxdata(context, 0);
if( pRe==0 ){
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
| > | | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
){
ReCompiled *pRe; /* Compiled regular expression */
const char *zPattern; /* The regular expression */
const unsigned char *zStr;/* String being searched */
const char *zErr; /* Compile error message */
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
(void)argc; /* Unused */
pRe = sqlite3_get_auxdata(context, 0);
if( pRe==0 ){
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
if( zErr ){
re_free(pRe);
sqlite3_result_error(context, zErr, -1);
return;
}
if( pRe==0 ){
sqlite3_result_error_nomem(context);
|
| ︙ | ︙ | |||
692 693 694 695 696 697 698 |
}
/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
int re_add_sql_func(sqlite3 *db){
| > | | > > > > > > > | 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 |
}
/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
int re_add_sql_func(sqlite3 *db){
int rc;
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
0, re_sql_func, 0, 0);
if( rc==SQLITE_OK ){
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
** of regexp(PATTERN,STRING). */
rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
(void*)db, re_sql_func, 0, 0);
}
return rc;
}
/*
** Run a "grep" over a single file read from disk.
*/
static void grep_file(ReCompiled *pRe, const char *zFile, FILE *in){
int ln = 0;
|
| ︙ | ︙ |
Changes to src/repolist.c.
| ︙ | ︙ | |||
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 |
struct RepoInfo {
char *zRepoName; /* Name of the repository file */
int isValid; /* True if zRepoName is a valid Fossil repository */
int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
** for the repository list. 2 means do use this
** repository but do not display it in the list. */
char *zProjName; /* Project Name. Memory from fossil_malloc() */
double rMTime; /* Last update. Julian day number */
};
#endif
/*
** Discover information about the repository given by
** pRepo->zRepoName. The discovered information is stored in other
** fields of the RepoInfo object.
*/
static void remote_repo_info(RepoInfo *pRepo){
sqlite3 *db;
sqlite3_stmt *pStmt;
int rc;
pRepo->isRepolistSkin = 0;
pRepo->isValid = 0;
pRepo->zProjName = 0;
pRepo->rMTime = 0.0;
g.dbIgnoreErrors++;
rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
if( rc ) goto finish_repo_list;
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
" WHERE name='repolist-skin'",
| > > | 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 |
struct RepoInfo {
char *zRepoName; /* Name of the repository file */
int isValid; /* True if zRepoName is a valid Fossil repository */
int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
** for the repository list. 2 means do use this
** repository but do not display it in the list. */
char *zProjName; /* Project Name. Memory from fossil_malloc() */
char *zLoginGroup; /* Name of login group, or NULL. Malloced() */
double rMTime; /* Last update. Julian day number */
};
#endif
/*
** Discover information about the repository given by
** pRepo->zRepoName. The discovered information is stored in other
** fields of the RepoInfo object.
*/
static void remote_repo_info(RepoInfo *pRepo){
sqlite3 *db;
sqlite3_stmt *pStmt;
int rc;
pRepo->isRepolistSkin = 0;
pRepo->isValid = 0;
pRepo->zProjName = 0;
pRepo->zLoginGroup = 0;
pRepo->rMTime = 0.0;
g.dbIgnoreErrors++;
rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
if( rc ) goto finish_repo_list;
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
" WHERE name='repolist-skin'",
|
| ︙ | ︙ | |||
67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
" WHERE name='project-name'",
-1, &pStmt, 0);
if( rc ) goto finish_repo_list;
if( sqlite3_step(pStmt)==SQLITE_ROW ){
pRepo->zProjName = fossil_strdup((char*)sqlite3_column_text(pStmt,0));
}
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(db, "SELECT max(mtime) FROM event", -1, &pStmt, 0);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
pRepo->rMTime = sqlite3_column_double(pStmt,0);
}
pRepo->isValid = 1;
sqlite3_finalize(pStmt);
| > > > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
" WHERE name='project-name'",
-1, &pStmt, 0);
if( rc ) goto finish_repo_list;
if( sqlite3_step(pStmt)==SQLITE_ROW ){
pRepo->zProjName = fossil_strdup((char*)sqlite3_column_text(pStmt,0));
}
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
" WHERE name='login-group-name'",
-1, &pStmt, 0);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
pRepo->zLoginGroup = fossil_strdup((char*)sqlite3_column_text(pStmt,0));
}
sqlite3_finalize(pStmt);
rc = sqlite3_prepare_v2(db, "SELECT max(mtime) FROM event", -1, &pStmt, 0);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
pRepo->rMTime = sqlite3_column_double(pStmt,0);
}
pRepo->isValid = 1;
sqlite3_finalize(pStmt);
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 |
g.localOpen = 0;
return 0;
}else{
Stmt q;
double rNow;
blob_append_sql(&html,
"<table border='0' class='sortable' data-init-sort='1'"
| | | > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
g.localOpen = 0;
return 0;
}else{
Stmt q;
double rNow;
blob_append_sql(&html,
"<table border='0' class='sortable' data-init-sort='1'"
" data-column-types='txtxkxt'><thead>\n"
"<tr><th>Filename<th width='20'>"
"<th>Project Name<th width='20'>"
"<th>Last Modified<th width='20'>"
"<th>Login Group</tr>\n"
"</thead><tbody>\n");
db_prepare(&q, "SELECT pathname"
" FROM sfile ORDER BY pathname COLLATE nocase;");
rNow = db_double(0, "SELECT julianday('now')");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
int nName = (int)strlen(zName);
|
| ︙ | ︙ | |||
221 222 223 224 225 226 227 |
if( x.zProjName ){
blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
fossil_free(x.zProjName);
}else{
blob_append_sql(&html, "<td></td><td></td>\n");
}
blob_append_sql(&html,
| | > > > > > > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
if( x.zProjName ){
blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
fossil_free(x.zProjName);
}else{
blob_append_sql(&html, "<td></td><td></td>\n");
}
blob_append_sql(&html,
"<td></td><td data-sortkey='%08x'>%h</td>\n",
iAge, zAge);
fossil_free(zAge);
if( x.zLoginGroup ){
blob_append_sql(&html, "<td></td><td>%h</td></tr>\n", x.zLoginGroup);
fossil_free(x.zLoginGroup);
}else{
blob_append_sql(&html, "<td></td><td></td></tr>\n");
}
sqlite3_free(zUrl);
}
db_finalize(&q);
blob_append_sql(&html,"</tbody></table>\n");
}
if( zSkinRepo ){
char *zNewBase = mprintf("%s/%s", g.zBaseURL, zSkinUrl);
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
197 198 199 200 201 202 203 |
"tagxref",
"ticket",
"ticketchng",
"unversioned",
};
int lwr = 0;
int upr = count(azAllowed) - 1;
| | | | | | | > > > > | | 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 |
"tagxref",
"ticket",
"ticketchng",
"unversioned",
};
int lwr = 0;
int upr = count(azAllowed) - 1;
int cmp = 0;
if( zArg1==0 ){
/* Some legacy versions of SQLite will sometimes send spurious
** READ authorizations that have no table name. These can be
** ignored. */
rc = SQLITE_IGNORE;
break;
}
while( lwr<=upr ){
int i = (lwr+upr)/2;
cmp = fossil_stricmp(zArg1, azAllowed[i]);
if( cmp<0 ){
upr = i - 1;
}else if( cmp>0 ){
lwr = i + 1;
}else{
break;
}
}
if( cmp ){
/* Always ok to access tables whose names begin with "fx_" */
cmp = sqlite3_strnicmp(zArg1, "fx_", 3);
}
if( cmp ){
*(char**)pError = mprintf("access to table \"%s\" is restricted",zArg1);
rc = SQLITE_DENY;
}else if( !g.perm.RdAddr && sqlite3_strnicmp(zArg2, "private_", 8)==0 ){
rc = SQLITE_IGNORE;
}
break;
}
default: {
*(char**)pError = mprintf("only SELECT statements are allowed");
rc = SQLITE_DENY;
|
| ︙ | ︙ | |||
977 978 979 980 981 982 983 |
**
** Submenu of the /rptview page can be extended with additional
** hyperlinks by providing query parameter(s) of the form rvsmplXY=Z.
** Optional ending XY consists of a digit X from the set {1,2,3,4,5}
** and an optional letter Y that (if present) must be either 'a' or 's'.
** Mandatory Z is a repo-local hyperlink's target (wihout leading '/').
**
| < | | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 |
**
** Submenu of the /rptview page can be extended with additional
** hyperlinks by providing query parameter(s) of the form rvsmplXY=Z.
** Optional ending XY consists of a digit X from the set {1,2,3,4,5}
** and an optional letter Y that (if present) must be either 'a' or 's'.
** Mandatory Z is a repo-local hyperlink's target (wihout leading '/').
**
** For details see the wiki page "branch/rptview-submenu-paralink".
*/
void rptview_page(void){
int count = 0;
int rn, rc;
char *zSql;
char *zTitle;
char *zOwner;
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
968 969 970 971 972 973 974 |
** entry. Hyperlinks that start with "/" are relative to the
** repository root.
**
** * The third term is an argument to the TH1 "capexpr" command.
** If capexpr evalutes to true, then the entry is shown. If not,
** the entry is omitted. "*" is always true. "{}" is never true.
**
| | | | | | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
** entry. Hyperlinks that start with "/" are relative to the
** repository root.
**
** * The third term is an argument to the TH1 "capexpr" command.
** If capexpr evalutes to true, then the entry is shown. If not,
** the entry is omitted. "*" is always true. "{}" is never true.
**
** * The fourth term is a list of extra class names to apply to the
** new menu entry. Some skins use classes "desktoponly" and
** "wideonly" to only show the entries when the web browser
** screen is wide or very wide, respectively.
**
** Some custom skins might not use this property. Whether the property
** is used or not a choice made by the skin designer. Some skins may add
** extra choices (such as the hamburger button) to the menu.
*/
/*
** SETTING: sitemap-extra width=70 block-text
|
| ︙ | ︙ | |||
1088 1089 1090 1091 1092 1093 1094 |
@ <li> The second term is a hyperlink to take when a user clicks on the
@ entry. Hyperlinks that start with "/" are relative to the
@ repository root.
@ <li> The third term is an argument to the TH1 "capexpr" command.
@ If capexpr evalutes to true, then the entry is shown. If not,
@ the entry is omitted. "*" is always true. "{}" is never true.
@ <li> The fourth term is a list of extra class names to apply to the new
| | | 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 |
@ <li> The second term is a hyperlink to take when a user clicks on the
@ entry. Hyperlinks that start with "/" are relative to the
@ repository root.
@ <li> The third term is an argument to the TH1 "capexpr" command.
@ If capexpr evalutes to true, then the entry is shown. If not,
@ the entry is omitted. "*" is always true. "{}" is never true.
@ <li> The fourth term is a list of extra class names to apply to the new
@ menu entry. Some skins use classes "desktoponly" and "wideonly"
@ to only show the entries when the web browser screen is wide or
@ very wide, respectively.
@ </ol>
@
@ <p>Some custom skins might not use this property. Whether the property
@ is used or not a choice made by the skin designer. Some skins may add extra
@ choices (such as the hamburger button) to the menu that are not shown
|
| ︙ | ︙ |
Changes to src/shell.c.
| ︙ | ︙ | |||
4152 4153 4154 4155 4156 4157 4158 |
memset(pApndFile, 0, sizeof(ApndFile));
pFile->pMethods = &apnd_io_methods;
pApndFile->iMark = -1; /* Append mark not yet written */
rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
if( rc==SQLITE_OK ){
rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
| < | | > > > | 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 |
memset(pApndFile, 0, sizeof(ApndFile));
pFile->pMethods = &apnd_io_methods;
pApndFile->iMark = -1; /* Append mark not yet written */
rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
if( rc==SQLITE_OK ){
rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
if( rc ){
pBaseFile->pMethods->xClose(pBaseFile);
}
}
if( rc ){
pFile->pMethods = 0;
return rc;
}
if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
/* The file being opened appears to be just an ordinary DB. Copy
** the base dispatch-table so this instance mimics the base VFS.
*/
|
| ︙ | ︙ | |||
4959 4960 4961 4962 4963 4964 4965 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
| | | | | > | 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
if( pB ){
pB->sign = !pB->sign;
decimal_add(pA, pB);
decimal_result(context, pA);
}
decimal_free(pA);
decimal_free(pB);
}
/* Aggregate funcion: decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
|
| ︙ | ︙ | |||
5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 | } rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0); #endif return rc; } /************************* End ../ext/misc/series.c ********************/ #ifdef SQLITE_HAVE_ZLIB /************************* Begin ../ext/misc/zipfile.c ******************/ /* ** 2017-12-26 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 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 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 |
}
rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
#endif
return rc;
}
/************************* End ../ext/misc/series.c ********************/
/************************* Begin ../ext/misc/regexp.c ******************/
/*
** 2012-11-13
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** The code in this file implements a compact but reasonably
** efficient regular-expression matcher for posix extended regular
** expressions against UTF8 text.
**
** This file is an SQLite extension. It registers a single function
** named "regexp(A,B)" where A is the regular expression and B is the
** string to be matched. By registering this function, SQLite will also
** then implement the "B regexp A" operator. Note that with the function
** the regular expression comes first, but with the operator it comes
** second.
**
** The following regular expression syntax is supported:
**
** X* zero or more occurrences of X
** X+ one or more occurrences of X
** X? zero or one occurrences of X
** X{p,q} between p and q occurrences of X
** (X) match X
** X|Y X or Y
** ^X X occurring at the beginning of the string
** X$ X occurring at the end of the string
** . Match any single character
** \c Character c where c is one of \{}()[]|*+?.
** \c C-language escapes for c in afnrtv. ex: \t or \n
** \uXXXX Where XXXX is exactly 4 hex digits, unicode value XXXX
** \xXX Where XX is exactly 2 hex digits, unicode value XX
** [abc] Any single character from the set abc
** [^abc] Any single character not in the set abc
** [a-z] Any single character in the range a-z
** [^a-z] Any single character not in the range a-z
** \b Word boundary
** \w Word character. [A-Za-z0-9_]
** \W Non-word character
** \d Digit
** \D Non-digit
** \s Whitespace character
** \S Non-whitespace character
**
** A nondeterministic finite automaton (NFA) is used for matching, so the
** performance is bounded by O(N*M) where N is the size of the regular
** expression and M is the size of the input string. The matcher never
** exhibits exponential behavior. Note that the X{p,q} operator expands
** to p copies of X following by q-p copies of X? and that the size of the
** regular expression in the O(N*M) performance bound is computed after
** this expansion.
*/
#include <string.h>
#include <stdlib.h>
/* #include "sqlite3ext.h" */
SQLITE_EXTENSION_INIT1
/*
** The following #defines change the names of some functions implemented in
** this file to prevent name collisions with C-library functions of the
** same name.
*/
#define re_match sqlite3re_match
#define re_compile sqlite3re_compile
#define re_free sqlite3re_free
/* The end-of-input character */
#define RE_EOF 0 /* End of input */
/* The NFA is implemented as sequence of opcodes taken from the following
** set. Each opcode has a single integer argument.
*/
#define RE_OP_MATCH 1 /* Match the one character in the argument */
#define RE_OP_ANY 2 /* Match any one character. (Implements ".") */
#define RE_OP_ANYSTAR 3 /* Special optimized version of .* */
#define RE_OP_FORK 4 /* Continue to both next and opcode at iArg */
#define RE_OP_GOTO 5 /* Jump to opcode at iArg */
#define RE_OP_ACCEPT 6 /* Halt and indicate a successful match */
#define RE_OP_CC_INC 7 /* Beginning of a [...] character class */
#define RE_OP_CC_EXC 8 /* Beginning of a [^...] character class */
#define RE_OP_CC_VALUE 9 /* Single value in a character class */
#define RE_OP_CC_RANGE 10 /* Range of values in a character class */
#define RE_OP_WORD 11 /* Perl word character [A-Za-z0-9_] */
#define RE_OP_NOTWORD 12 /* Not a perl word character */
#define RE_OP_DIGIT 13 /* digit: [0-9] */
#define RE_OP_NOTDIGIT 14 /* Not a digit */
#define RE_OP_SPACE 15 /* space: [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE 16 /* Not a digit */
#define RE_OP_BOUNDARY 17 /* Boundary between word and non-word */
/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;
/* Because this is an NFA and not a DFA, multiple states can be active at
** once. An instance of the following object records all active states in
** the NFA. The implementation is optimized for the common case where the
** number of actives states is small.
*/
typedef struct ReStateSet {
unsigned nState; /* Number of current states */
ReStateNumber *aState; /* Current states */
} ReStateSet;
/* An input string read one character at a time.
*/
typedef struct ReInput ReInput;
struct ReInput {
const unsigned char *z; /* All text */
int i; /* Next byte to read */
int mx; /* EOF when i>=mx */
};
/* A compiled NFA (or an NFA that is in the process of being compiled) is
** an instance of the following object.
*/
typedef struct ReCompiled ReCompiled;
struct ReCompiled {
ReInput sIn; /* Regular expression text */
const char *zErr; /* Error message to return */
char *aOp; /* Operators for the virtual machine */
int *aArg; /* Arguments to each operator */
unsigned (*xNextChar)(ReInput*); /* Next character function */
unsigned char zInit[12]; /* Initial text to match */
int nInit; /* Number of characters in zInit */
unsigned nState; /* Number of entries in aOp[] and aArg[] */
unsigned nAlloc; /* Slots allocated for aOp[] and aArg[] */
};
/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
unsigned i;
for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}
/* Extract the next unicode character from *pzIn and return it. Advance
** *pzIn to the first byte past the end of the character returned. To
** be clear: this routine converts utf8 to unicode. This routine is
** optimized for the common case where the next character is a single byte.
*/
static unsigned re_next_char(ReInput *p){
unsigned c;
if( p->i>=p->mx ) return 0;
c = p->z[p->i++];
if( c>=0x80 ){
if( (c&0xe0)==0xc0 && p->i<p->mx && (p->z[p->i]&0xc0)==0x80 ){
c = (c&0x1f)<<6 | (p->z[p->i++]&0x3f);
if( c<0x80 ) c = 0xfffd;
}else if( (c&0xf0)==0xe0 && p->i+1<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 ){
c = (c&0x0f)<<12 | ((p->z[p->i]&0x3f)<<6) | (p->z[p->i+1]&0x3f);
p->i += 2;
if( c<=0x7ff || (c>=0xd800 && c<=0xdfff) ) c = 0xfffd;
}else if( (c&0xf8)==0xf0 && p->i+3<p->mx && (p->z[p->i]&0xc0)==0x80
&& (p->z[p->i+1]&0xc0)==0x80 && (p->z[p->i+2]&0xc0)==0x80 ){
c = (c&0x07)<<18 | ((p->z[p->i]&0x3f)<<12) | ((p->z[p->i+1]&0x3f)<<6)
| (p->z[p->i+2]&0x3f);
p->i += 3;
if( c<=0xffff || c>0x10ffff ) c = 0xfffd;
}else{
c = 0xfffd;
}
}
return c;
}
static unsigned re_next_char_nocase(ReInput *p){
unsigned c = re_next_char(p);
if( c>='A' && c<='Z' ) c += 'a' - 'A';
return c;
}
/* Return true if c is a perl "word" character: [A-Za-z0-9_] */
static int re_word_char(int c){
return (c>='0' && c<='9') || (c>='a' && c<='z')
|| (c>='A' && c<='Z') || c=='_';
}
/* Return true if c is a "digit" character: [0-9] */
static int re_digit_char(int c){
return (c>='0' && c<='9');
}
/* Return true if c is a perl "space" character: [ \t\r\n\v\f] */
static int re_space_char(int c){
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
/* Run a compiled regular expression on the zero-terminated input
** string zIn[]. Return true on a match and false if there is no match.
*/
static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
ReStateSet aStateSet[2], *pThis, *pNext;
ReStateNumber aSpace[100];
ReStateNumber *pToFree;
unsigned int i = 0;
unsigned int iSwap = 0;
int c = RE_EOF+1;
int cPrev = 0;
int rc = 0;
ReInput in;
in.z = zIn;
in.i = 0;
in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);
/* Look for the initial prefix match, if there is one. */
if( pRe->nInit ){
unsigned char x = pRe->zInit[0];
while( in.i+pRe->nInit<=in.mx
&& (zIn[in.i]!=x ||
strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
){
in.i++;
}
if( in.i+pRe->nInit>in.mx ) return 0;
}
if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
pToFree = 0;
aStateSet[0].aState = aSpace;
}else{
pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
if( pToFree==0 ) return -1;
aStateSet[0].aState = pToFree;
}
aStateSet[1].aState = &aStateSet[0].aState[pRe->nState];
pNext = &aStateSet[1];
pNext->nState = 0;
re_add_state(pNext, 0);
while( c!=RE_EOF && pNext->nState>0 ){
cPrev = c;
c = pRe->xNextChar(&in);
pThis = pNext;
pNext = &aStateSet[iSwap];
iSwap = 1 - iSwap;
pNext->nState = 0;
for(i=0; i<pThis->nState; i++){
int x = pThis->aState[i];
switch( pRe->aOp[x] ){
case RE_OP_MATCH: {
if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
break;
}
case RE_OP_ANY: {
if( c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_WORD: {
if( re_word_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTWORD: {
if( !re_word_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_DIGIT: {
if( re_digit_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTDIGIT: {
if( !re_digit_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_SPACE: {
if( re_space_char(c) ) re_add_state(pNext, x+1);
break;
}
case RE_OP_NOTSPACE: {
if( !re_space_char(c) && c!=0 ) re_add_state(pNext, x+1);
break;
}
case RE_OP_BOUNDARY: {
if( re_word_char(c)!=re_word_char(cPrev) ) re_add_state(pThis, x+1);
break;
}
case RE_OP_ANYSTAR: {
re_add_state(pNext, x);
re_add_state(pThis, x+1);
break;
}
case RE_OP_FORK: {
re_add_state(pThis, x+pRe->aArg[x]);
re_add_state(pThis, x+1);
break;
}
case RE_OP_GOTO: {
re_add_state(pThis, x+pRe->aArg[x]);
break;
}
case RE_OP_ACCEPT: {
rc = 1;
goto re_match_end;
}
case RE_OP_CC_EXC: {
if( c==0 ) break;
/* fall-through */
}
case 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;
j = -1;
}
}else{
if( pRe->aArg[x+j]<=c && pRe->aArg[x+j+1]>=c ){
hit = 1;
j = -1;
}else{
j++;
}
}
}
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
if( hit ) re_add_state(pNext, x+n);
break;
}
}
}
}
for(i=0; i<pNext->nState; i++){
if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
}
re_match_end:
sqlite3_free(pToFree);
return rc;
}
/* Resize the opcode and argument arrays for an RE under construction.
*/
static int re_resize(ReCompiled *p, int N){
char *aOp;
int *aArg;
aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
if( aOp==0 ) return 1;
p->aOp = aOp;
aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
if( aArg==0 ) return 1;
p->aArg = aArg;
p->nAlloc = N;
return 0;
}
/* Insert a new opcode and argument into an RE under construction. The
** insertion point is just prior to existing opcode iBefore.
*/
static int re_insert(ReCompiled *p, int iBefore, int op, int arg){
int i;
if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
for(i=p->nState; i>iBefore; i--){
p->aOp[i] = p->aOp[i-1];
p->aArg[i] = p->aArg[i-1];
}
p->nState++;
p->aOp[iBefore] = (char)op;
p->aArg[iBefore] = arg;
return iBefore;
}
/* Append a new opcode and argument to the end of the RE under construction.
*/
static int re_append(ReCompiled *p, int op, int arg){
return re_insert(p, p->nState, op, arg);
}
/* Make a copy of N opcodes starting at iStart onto the end of the RE
** under construction.
*/
static void re_copy(ReCompiled *p, int iStart, int N){
if( p->nState+N>=p->nAlloc && re_resize(p, p->nAlloc*2+N) ) return;
memcpy(&p->aOp[p->nState], &p->aOp[iStart], N*sizeof(p->aOp[0]));
memcpy(&p->aArg[p->nState], &p->aArg[iStart], N*sizeof(p->aArg[0]));
p->nState += N;
}
/* Return true if c is a hexadecimal digit character: [0-9a-fA-F]
** If c is a hex digit, also set *pV = (*pV)*16 + valueof(c). If
** c is not a hex digit *pV is unchanged.
*/
static int re_hex(int c, int *pV){
if( c>='0' && c<='9' ){
c -= '0';
}else if( c>='a' && c<='f' ){
c -= 'a' - 10;
}else if( c>='A' && c<='F' ){
c -= 'A' - 10;
}else{
return 0;
}
*pV = (*pV)*16 + (c & 0xff);
return 1;
}
/* A backslash character has been seen, read the next character and
** return its interpretation.
*/
static unsigned re_esc_char(ReCompiled *p){
static const char zEsc[] = "afnrtv\\()*.+?[$^{|}]";
static const char zTrans[] = "\a\f\n\r\t\v";
int i, v = 0;
char c;
if( p->sIn.i>=p->sIn.mx ) return 0;
c = p->sIn.z[p->sIn.i];
if( c=='u' && p->sIn.i+4<p->sIn.mx ){
const unsigned char *zIn = p->sIn.z + p->sIn.i;
if( re_hex(zIn[1],&v)
&& re_hex(zIn[2],&v)
&& re_hex(zIn[3],&v)
&& re_hex(zIn[4],&v)
){
p->sIn.i += 5;
return v;
}
}
if( c=='x' && p->sIn.i+2<p->sIn.mx ){
const unsigned char *zIn = p->sIn.z + p->sIn.i;
if( re_hex(zIn[1],&v)
&& re_hex(zIn[2],&v)
){
p->sIn.i += 3;
return v;
}
}
for(i=0; zEsc[i] && zEsc[i]!=c; i++){}
if( zEsc[i] ){
if( i<6 ) c = zTrans[i];
p->sIn.i++;
}else{
p->zErr = "unknown \\ escape";
}
return c;
}
/* Forward declaration */
static const char *re_subcompile_string(ReCompiled*);
/* Peek at the next byte of input */
static unsigned char rePeek(ReCompiled *p){
return p->sIn.i<p->sIn.mx ? p->sIn.z[p->sIn.i] : 0;
}
/* Compile RE text into a sequence of opcodes. Continue up to the
** first unmatched ")" character, then return. If an error is found,
** return a pointer to the error message string.
*/
static const char *re_subcompile_re(ReCompiled *p){
const char *zErr;
int iStart, iEnd, iGoto;
iStart = p->nState;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
while( rePeek(p)=='|' ){
iEnd = p->nState;
re_insert(p, iStart, RE_OP_FORK, iEnd + 2 - iStart);
iGoto = re_append(p, RE_OP_GOTO, 0);
p->sIn.i++;
zErr = re_subcompile_string(p);
if( zErr ) return zErr;
p->aArg[iGoto] = p->nState - iGoto;
}
return 0;
}
/* Compile an element of regular expression text (anything that can be
** an operand to the "|" operator). Return NULL on success or a pointer
** to the error message if there is a problem.
*/
static const char *re_subcompile_string(ReCompiled *p){
int iPrev = -1;
int iStart;
unsigned c;
const char *zErr;
while( (c = p->xNextChar(&p->sIn))!=0 ){
iStart = p->nState;
switch( c ){
case '|':
case '$':
case ')': {
p->sIn.i--;
return 0;
}
case '(': {
zErr = re_subcompile_re(p);
if( zErr ) return zErr;
if( rePeek(p)!=')' ) return "unmatched '('";
p->sIn.i++;
break;
}
case '.': {
if( rePeek(p)=='*' ){
re_append(p, RE_OP_ANYSTAR, 0);
p->sIn.i++;
}else{
re_append(p, RE_OP_ANY, 0);
}
break;
}
case '*': {
if( iPrev<0 ) return "'*' without operand";
re_insert(p, iPrev, RE_OP_GOTO, p->nState - iPrev + 1);
re_append(p, RE_OP_FORK, iPrev - p->nState + 1);
break;
}
case '+': {
if( iPrev<0 ) return "'+' without operand";
re_append(p, RE_OP_FORK, iPrev - p->nState);
break;
}
case '?': {
if( iPrev<0 ) return "'?' without operand";
re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
break;
}
case '{': {
int m = 0, n = 0;
int sz, j;
if( iPrev<0 ) return "'{m,n}' without operand";
while( (c=rePeek(p))>='0' && c<='9' ){ m = m*10 + c - '0'; p->sIn.i++; }
n = m;
if( c==',' ){
p->sIn.i++;
n = 0;
while( (c=rePeek(p))>='0' && c<='9' ){ n = n*10 + c-'0'; p->sIn.i++; }
}
if( c!='}' ) return "unmatched '{'";
if( n>0 && n<m ) return "n less than m in '{m,n}'";
p->sIn.i++;
sz = p->nState - iPrev;
if( m==0 ){
if( n==0 ) return "both m and n are zero in '{m,n}'";
re_insert(p, iPrev, RE_OP_FORK, sz+1);
n--;
}else{
for(j=1; j<m; j++) re_copy(p, iPrev, sz);
}
for(j=m; j<n; j++){
re_append(p, RE_OP_FORK, sz+1);
re_copy(p, iPrev, sz);
}
if( n==0 && m>0 ){
re_append(p, RE_OP_FORK, -sz);
}
break;
}
case '[': {
int iFirst = p->nState;
if( rePeek(p)=='^' ){
re_append(p, RE_OP_CC_EXC, 0);
p->sIn.i++;
}else{
re_append(p, RE_OP_CC_INC, 0);
}
while( (c = p->xNextChar(&p->sIn))!=0 ){
if( c=='[' && rePeek(p)==':' ){
return "POSIX character classes not supported";
}
if( c=='\\' ) c = re_esc_char(p);
if( rePeek(p)=='-' ){
re_append(p, RE_OP_CC_RANGE, c);
p->sIn.i++;
c = p->xNextChar(&p->sIn);
if( c=='\\' ) c = re_esc_char(p);
re_append(p, RE_OP_CC_RANGE, c);
}else{
re_append(p, RE_OP_CC_VALUE, c);
}
if( rePeek(p)==']' ){ p->sIn.i++; break; }
}
if( c==0 ) return "unclosed '['";
p->aArg[iFirst] = p->nState - iFirst;
break;
}
case '\\': {
int specialOp = 0;
switch( rePeek(p) ){
case 'b': specialOp = RE_OP_BOUNDARY; break;
case 'd': specialOp = RE_OP_DIGIT; break;
case 'D': specialOp = RE_OP_NOTDIGIT; break;
case 's': specialOp = RE_OP_SPACE; break;
case 'S': specialOp = RE_OP_NOTSPACE; break;
case 'w': specialOp = RE_OP_WORD; break;
case 'W': specialOp = RE_OP_NOTWORD; break;
}
if( specialOp ){
p->sIn.i++;
re_append(p, specialOp, 0);
}else{
c = re_esc_char(p);
re_append(p, RE_OP_MATCH, c);
}
break;
}
default: {
re_append(p, RE_OP_MATCH, c);
break;
}
}
iPrev = iStart;
}
return 0;
}
/* Free and reclaim all the memory used by a previously compiled
** regular expression. Applications should invoke this routine once
** for every call to re_compile() to avoid memory leaks.
*/
static void re_free(ReCompiled *pRe){
if( pRe ){
sqlite3_free(pRe->aOp);
sqlite3_free(pRe->aArg);
sqlite3_free(pRe);
}
}
/*
** Compile a textual regular expression in zIn[] into a compiled regular
** expression suitable for us by re_match() and return a pointer to the
** compiled regular expression in *ppRe. Return NULL on success or an
** error message if something goes wrong.
*/
static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
ReCompiled *pRe;
const char *zErr;
int i, j;
*ppRe = 0;
pRe = sqlite3_malloc( sizeof(*pRe) );
if( pRe==0 ){
return "out of memory";
}
memset(pRe, 0, sizeof(*pRe));
pRe->xNextChar = noCase ? re_next_char_nocase : re_next_char;
if( re_resize(pRe, 30) ){
re_free(pRe);
return "out of memory";
}
if( zIn[0]=='^' ){
zIn++;
}else{
re_append(pRe, RE_OP_ANYSTAR, 0);
}
pRe->sIn.z = (unsigned char*)zIn;
pRe->sIn.i = 0;
pRe->sIn.mx = (int)strlen(zIn);
zErr = re_subcompile_re(pRe);
if( zErr ){
re_free(pRe);
return zErr;
}
if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
re_append(pRe, RE_OP_MATCH, RE_EOF);
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else if( pRe->sIn.i>=pRe->sIn.mx ){
re_append(pRe, RE_OP_ACCEPT, 0);
*ppRe = pRe;
}else{
re_free(pRe);
return "unrecognized character";
}
/* The following is a performance optimization. If the regex begins with
** ".*" (if the input regex lacks an initial "^") and afterwards there are
** one or more matching characters, enter those matching characters into
** zInit[]. The re_match() routine can then search ahead in the input
** string looking for the initial match without having to run the whole
** regex engine over the string. Do not worry able trying to match
** unicode characters beyond plane 0 - those are very rare and this is
** just an optimization. */
if( pRe->aOp[0]==RE_OP_ANYSTAR && !noCase ){
for(j=0, i=1; j<(int)sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
unsigned x = pRe->aArg[i];
if( x<=127 ){
pRe->zInit[j++] = (unsigned char)x;
}else if( x<=0xfff ){
pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else if( x<=0xffff ){
pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
pRe->zInit[j++] = 0x80 | (x&0x3f);
}else{
break;
}
}
if( j>0 && pRe->zInit[j-1]==0 ) j--;
pRe->nInit = j;
}
return pRe->zErr;
}
/*
** Implementation of the regexp() SQL function. This function implements
** the build-in REGEXP operator. The first argument to the function is the
** pattern and the second argument is the string. So, the SQL statements:
**
** A REGEXP B
**
** is implemented as regexp(B,A).
*/
static void re_sql_func(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
ReCompiled *pRe; /* Compiled regular expression */
const char *zPattern; /* The regular expression */
const unsigned char *zStr;/* String being searched */
const char *zErr; /* Compile error message */
int setAux = 0; /* True to invoke sqlite3_set_auxdata() */
(void)argc; /* Unused */
pRe = sqlite3_get_auxdata(context, 0);
if( pRe==0 ){
zPattern = (const char*)sqlite3_value_text(argv[0]);
if( zPattern==0 ) return;
zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
if( zErr ){
re_free(pRe);
sqlite3_result_error(context, zErr, -1);
return;
}
if( pRe==0 ){
sqlite3_result_error_nomem(context);
return;
}
setAux = 1;
}
zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
if( zStr!=0 ){
sqlite3_result_int(context, re_match(pRe, zStr, -1));
}
if( setAux ){
sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
}
}
/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
*/
#ifdef _WIN32
#endif
int sqlite3_regexp_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused */
rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
0, re_sql_func, 0, 0);
if( rc==SQLITE_OK ){
/* The regexpi(PATTERN,STRING) function is a case-insensitive version
** of regexp(PATTERN,STRING). */
rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
(void*)db, re_sql_func, 0, 0);
}
return rc;
}
/************************* End ../ext/misc/regexp.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
** 2017-12-26
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
|
| ︙ | ︙ | |||
5914 5915 5916 5917 5918 5919 5920 5921 5922 | #include <zlib.h> #ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_AMALGAMATION /* typedef sqlite3_int64 i64; */ /* typedef unsigned char u8; */ | > > > > > > > > > > > > > > | | | 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 | #include <zlib.h> #ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_AMALGAMATION #ifndef UINT32_TYPE # ifdef HAVE_UINT32_T # define UINT32_TYPE uint32_t # else # define UINT32_TYPE unsigned int # endif #endif #ifndef UINT16_TYPE # ifdef HAVE_UINT16_T # define UINT16_TYPE uint16_t # else # define UINT16_TYPE unsigned short int # endif #endif /* 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)) |
| ︙ | ︙ | |||
6584 6585 6586 6587 6588 6589 6590 |
** Bits 00-04: day
** Bits 05-08: month (1-12)
** Bits 09-15: years from 1980
**
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/
static u32 zipfileMtime(ZipfileCDS *pCDS){
| > > | | | < < | | | < < < < < | | | < | | < < | < < | < > | | 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 |
** Bits 00-04: day
** Bits 05-08: month (1-12)
** Bits 09-15: years from 1980
**
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/
static u32 zipfileMtime(ZipfileCDS *pCDS){
int Y,M,D,X1,X2,A,B,sec,min,hr;
i64 JDsec;
Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
M = ((pCDS->mDate >> 5) & 0x0F);
D = (pCDS->mDate & 0x1F);
sec = (pCDS->mTime & 0x1F)*2;
min = (pCDS->mTime >> 5) & 0x3F;
hr = (pCDS->mTime >> 11) & 0x1F;
if( M<=2 ){
Y--;
M += 12;
}
X1 = 36525*(Y+4716)/100;
X2 = 306001*(M+1)/10000;
A = Y/100;
B = 2 - A + (A/4);
JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
return (u32)(JDsec - (i64)24405875*(i64)8640);
}
/*
** The opposite of zipfileMtime(). This function populates the mTime and
** mDate fields of the CDS structure passed as the first argument according
** to the UNIX timestamp value passed as the second.
*/
|
| ︙ | ︙ | |||
8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 |
int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
zipfileStep, zipfileFinal
);
}
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
# define zipfileRegister(x) SQLITE_OK
#endif
#ifdef _WIN32
| > > > > | 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 |
int rc = sqlite3_create_module(db, "zipfile" , &zipfileModule, 0);
if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0,
zipfileStep, zipfileFinal
);
}
assert( sizeof(i64)==8 );
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(u8)==1 );
return rc;
}
#else /* SQLITE_OMIT_VIRTUALTABLE */
# define zipfileRegister(x) SQLITE_OK
#endif
#ifdef _WIN32
|
| ︙ | ︙ | |||
13067 13068 13069 13070 13071 13072 13073 |
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
sqlite3_exec(p->db,
"CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
" key TEXT PRIMARY KEY,\n"
| | | 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 |
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
sqlite3_exec(p->db,
"CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
" key TEXT PRIMARY KEY,\n"
" value\n"
") WITHOUT ROWID;",
0, 0, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
}
/*
|
| ︙ | ︙ | |||
14130 14131 14132 14133 14134 14135 14136 | " -x Send output as CSV to a spreadsheet (same as \".excel\")", #ifdef SQLITE_DEBUG ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", #endif ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", | | | | 14915 14916 14917 14918 14919 14920 14921 14922 14923 14924 14925 14926 14927 14928 14929 14930 | " -x Send output as CSV to a spreadsheet (same as \".excel\")", #ifdef SQLITE_DEBUG ".oom ?--repeat M? ?N? Simulate an OOM error on the N-th allocation", #endif ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", " Options:", " --append Use appendvfs to append database to the end of FILE", #ifndef SQLITE_OMIT_DESERIALIZE " --deserialize Load into memory using sqlite3_deserialize()", " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", " --nofollow Do not follow symbolic links", " --readonly Open FILE readonly", " --zip FILE is a ZIP archive", |
| ︙ | ︙ | |||
14452 14453 14454 14455 14456 14457 14458 |
rc = SHELL_OPEN_ZIPFILE;
}
}
fclose(f);
return rc;
}
| | | 15237 15238 15239 15240 15241 15242 15243 15244 15245 15246 15247 15248 15249 15250 15251 |
rc = SHELL_OPEN_ZIPFILE;
}
}
fclose(f);
return rc;
}
#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->zDbFilename. If p->zDbFilename
** is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
unsigned char *a = 0;
|
| ︙ | ︙ | |||
14541 14542 14543 14544 14545 14546 14547 |
}
p->lineno = nLine;
}
sqlite3_free(a);
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
| | | 15326 15327 15328 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 |
}
p->lineno = nLine;
}
sqlite3_free(a);
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */
/*
** Scalar function "shell_int32". The first argument to this function
** must be a blob. The second a non-negative integer. This function
** reads and returns a 32-bit big-endian integer from byte
** offset (4*<arg2>) of the blob.
*/
|
| ︙ | ︙ | |||
14767 14768 14769 14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 |
sqlite3_enable_load_extension(p->db, 1);
#endif
sqlite3_fileio_init(p->db, 0, 0);
sqlite3_shathree_init(p->db, 0, 0);
sqlite3_completion_init(p->db, 0, 0);
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
#ifdef SQLITE_HAVE_ZLIB
sqlite3_zipfile_init(p->db, 0, 0);
| > | 15552 15553 15554 15555 15556 15557 15558 15559 15560 15561 15562 15563 15564 15565 15566 |
sqlite3_enable_load_extension(p->db, 1);
#endif
sqlite3_fileio_init(p->db, 0, 0);
sqlite3_shathree_init(p->db, 0, 0);
sqlite3_completion_init(p->db, 0, 0);
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_regexp_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
#ifdef SQLITE_HAVE_ZLIB
sqlite3_zipfile_init(p->db, 0, 0);
|
| ︙ | ︙ | |||
14802 14803 14804 14805 14806 14807 14808 |
#endif
if( p->openMode==SHELL_OPEN_ZIPFILE ){
char *zSql = sqlite3_mprintf(
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
| | | 15588 15589 15590 15591 15592 15593 15594 15595 15596 15597 15598 15599 15600 15601 15602 |
#endif
if( p->openMode==SHELL_OPEN_ZIPFILE ){
char *zSql = sqlite3_mprintf(
"CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
#ifndef SQLITE_OMIT_DESERIALIZE
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int rc;
int nData = 0;
unsigned char *aData;
if( p->openMode==SHELL_OPEN_DESERIALIZE ){
aData = (unsigned char*)readFile(p->zDbFilename, &nData);
|
| ︙ | ︙ | |||
15931 15932 15933 15934 15935 15936 15937 |
const char *zSql =
"SELECT "
" 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
" || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
" || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
", "
| | | | 16717 16718 16719 16720 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 16737 16738 16739 16740 16741 16742 16743 16744 16745 16746 16747 16748 16749 16750 16751 |
const char *zSql =
"SELECT "
" 'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
" || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
" || fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
", "
" 'SEARCH ' || s.name || ' USING COVERING INDEX*('"
" || group_concat('*=?', ' AND ') || ')'"
", "
" s.name || '(' || group_concat(f.[from], ', ') || ')'"
", "
" f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
", "
" 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
" || ' ON ' || quote(s.name) || '('"
" || group_concat(quote(f.[from]) ||"
" fkey_collate_clause("
" f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
" || ');'"
", "
" f.[table] "
"FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
"LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
"GROUP BY s.name, f.id "
"ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
;
const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";
for(i=2; i<nArg; i++){
int n = strlen30(azArg[i]);
if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
bVerbose = 1;
}
else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
|
| ︙ | ︙ | |||
16869 16870 16871 16872 16873 16874 16875 16876 16877 16878 16879 16880 16881 16882 |
int rc = *pRc;
if( rc==SQLITE_OK ){
char *zErr = 0;
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
raw_printf(stderr, "SQL error: %s\n", zErr);
}
*pRc = rc;
}
}
/*
** Like shellExec(), except that zFmt is a printf() style format string.
*/
| > | 17655 17656 17657 17658 17659 17660 17661 17662 17663 17664 17665 17666 17667 17668 17669 |
int rc = *pRc;
if( rc==SQLITE_OK ){
char *zErr = 0;
rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
if( rc!=SQLITE_OK ){
raw_printf(stderr, "SQL error: %s\n", zErr);
}
sqlite3_free(zErr);
*pRc = rc;
}
}
/*
** Like shellExec(), except that zFmt is a printf() style format string.
*/
|
| ︙ | ︙ | |||
17890 17891 17892 17893 17894 17895 17896 |
}else
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
sqlite3_free(zLike);
goto meta_command_exit;
}
| > > > > > > > > > > > > > > > | | < | | > | 18677 18678 18679 18680 18681 18682 18683 18684 18685 18686 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 18710 |
}else
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
sqlite3_free(zLike);
goto meta_command_exit;
}
}else{
/* azArg[i] contains a LIKE pattern. This ".dump" request should
** only dump data for tables for which either the table name matches
** the LIKE pattern, or the table appears to be a shadow table of
** a virtual table for which the name matches the LIKE pattern.
*/
char *zExpr = sqlite3_mprintf(
"name LIKE %Q ESCAPE '\\' OR EXISTS ("
" SELECT 1 FROM sqlite_schema WHERE "
" name LIKE %Q ESCAPE '\\' AND"
" sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
" substr(o.name, 1, length(name)+1) == (name||'_')"
")", azArg[i], azArg[i]
);
if( zLike ){
zLike = sqlite3_mprintf("%z OR %z", zLike, zExpr);
}else{
zLike = zExpr;
}
}
}
open_db(p, 0);
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
/* When playing back a "dump", the content might appear in an order
|
| ︙ | ︙ | |||
17916 17917 17918 17919 17920 17921 17922 |
/* Set writable_schema=ON since doing so forces SQLite to initialize
** as much of the schema as it can even if the sqlite_schema table is
** corrupt. */
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
p->nErr = 0;
if( zLike==0 ) zLike = sqlite3_mprintf("true");
zSql = sqlite3_mprintf(
| | | | 18718 18719 18720 18721 18722 18723 18724 18725 18726 18727 18728 18729 18730 18731 18732 18733 18734 18735 18736 18737 18738 18739 18740 18741 18742 |
/* Set writable_schema=ON since doing so forces SQLite to initialize
** as much of the schema as it can even if the sqlite_schema table is
** corrupt. */
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
p->nErr = 0;
if( zLike==0 ) zLike = sqlite3_mprintf("true");
zSql = sqlite3_mprintf(
"SELECT name, type, sql FROM sqlite_schema AS o "
"WHERE (%s) AND type=='table'"
" AND sql NOT NULL"
" ORDER BY tbl_name='sqlite_sequence', rowid",
zLike
);
run_schema_dump_query(p,zSql);
sqlite3_free(zSql);
if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
zSql = sqlite3_mprintf(
"SELECT sql FROM sqlite_schema AS o "
"WHERE (%s) AND sql NOT NULL"
" AND type IN ('index','trigger','view')",
zLike
);
run_table_dump_query(p, zSql);
sqlite3_free(zSql);
}
|
| ︙ | ︙ | |||
18173 18174 18175 18176 18177 18178 18179 |
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
raw_printf(p->out, "%s\n", zBuf);
}
}else
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
| < | 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 18986 18987 18988 |
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
raw_printf(p->out, "%s\n", zBuf);
}
}else
if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
ShellState data;
int doStats = 0;
memcpy(&data, p, sizeof(data));
data.showHeader = 0;
data.cMode = data.mode = MODE_Semi;
if( nArg==2 && optionMatch(azArg[1], "indent") ){
data.cMode = data.mode = MODE_Pretty;
nArg = 1;
|
| ︙ | ︙ | |||
18195 18196 18197 18198 18199 18200 18201 |
rc = sqlite3_exec(p->db,
"SELECT sql FROM"
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
" FROM sqlite_schema UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
| | | | | | 18996 18997 18998 18999 19000 19001 19002 19003 19004 19005 19006 19007 19008 19009 19010 19011 19012 19013 19014 19015 19016 19017 19018 19019 19020 19021 19022 19023 19024 19025 19026 19027 19028 19029 19030 19031 |
rc = sqlite3_exec(p->db,
"SELECT sql FROM"
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
" FROM sqlite_schema UNION ALL"
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
"ORDER BY rowid",
callback, &data, 0
);
if( rc==SQLITE_OK ){
sqlite3_stmt *pStmt;
rc = sqlite3_prepare_v2(p->db,
"SELECT rowid FROM sqlite_schema"
" WHERE name GLOB 'sqlite_stat[134]'",
-1, &pStmt, 0);
doStats = sqlite3_step(pStmt)==SQLITE_ROW;
sqlite3_finalize(pStmt);
}
if( doStats==0 ){
raw_printf(p->out, "/* No STAT tables available */\n");
}else{
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
callback, &data, 0);
data.cMode = data.mode = MODE_Insert;
data.zDestTable = "sqlite_stat1";
shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
data.zDestTable = "sqlite_stat4";
shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}
}else
if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
if( nArg==2 ){
p->showHeader = booleanValue(azArg[1]);
|
| ︙ | ︙ | |||
18864 18865 18866 18867 18868 18869 18870 |
#endif
}else if( optionMatch(z, "append") ){
p->openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
| | | | 19665 19666 19667 19668 19669 19670 19671 19672 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 |
#endif
}else if( optionMatch(z, "append") ){
p->openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY;
}else if( optionMatch(z, "nofollow") ){
p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
}else if( optionMatch(z, "hexdb") ){
p->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;
|
| ︙ | ︙ | |||
20109 20110 20111 20112 20113 20114 20115 20116 20117 20118 20119 20120 20121 20122 |
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
};
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;
| > | 20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 20922 20923 20924 |
{ "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
#endif
{ "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
{ "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
{ "tune", SQLITE_TESTCTRL_TUNE, "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;
|
| ︙ | ︙ | |||
20253 20254 20255 20256 20257 20258 20259 |
rc2 = sqlite3_test_control(testctrl, p->db, &x);
utf8_printf(p->out, "%llu\n", x);
isOk = 3;
break;
}
#ifdef YYCOVERAGE
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 21055 21056 21057 21058 21059 21060 21061 21062 21063 21064 21065 21066 21067 21068 21069 21070 21071 21072 21073 21074 21075 21076 21077 21078 21079 21080 21081 21082 21083 21084 21085 21086 21087 21088 21089 21090 21091 21092 21093 21094 21095 21096 21097 21098 21099 21100 21101 21102 |
rc2 = sqlite3_test_control(testctrl, p->db, &x);
utf8_printf(p->out, "%llu\n", x);
isOk = 3;
break;
}
#ifdef YYCOVERAGE
case SQLITE_TESTCTRL_PARSER_COVERAGE: {
if( nArg==2 ){
sqlite3_test_control(testctrl, p->out);
isOk = 3;
}
break;
}
#endif
#ifdef SQLITE_DEBUG
case SQLITE_TESTCTRL_TUNE: {
if( nArg==4 ){
int id = (int)integerValue(azArg[2]);
int val = (int)integerValue(azArg[3]);
sqlite3_test_control(testctrl, id, &val);
isOk = 3;
}else if( nArg==3 ){
int id = (int)integerValue(azArg[2]);
sqlite3_test_control(testctrl, -id, &rc2);
isOk = 1;
}else if( nArg==2 ){
int id = 1;
while(1){
int val = 0;
rc2 = sqlite3_test_control(testctrl, -id, &val);
if( rc2!=SQLITE_OK ) break;
if( id>1 ) utf8_printf(p->out, " ");
utf8_printf(p->out, "%d: %d", id, val);
id++;
}
if( id>1 ) utf8_printf(p->out, "\n");
isOk = 3;
}
break;
}
#endif
}
}
if( isOk==0 && iCtrl>=0 ){
utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
rc = 1;
}else if( isOk==1 ){
|
| ︙ | ︙ | |||
20855 20856 20857 20858 20859 20860 20861 | " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -box set output mode to 'box'\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" | | | | 21686 21687 21688 21689 21690 21691 21692 21693 21694 21695 21696 21697 21698 21699 21700 21701 21702 21703 21704 21705 21706 21707 21708 21709 21710 21711 21712 21713 21714 21715 21716 21717 | " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -box set output mode to 'box'\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) " -deserialize open the database using sqlite3_deserialize()\n" #endif " -echo print commands before execution\n" " -init FILENAME read/process named file\n" " -[no]header turn headers on or off\n" #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) " -heap SIZE Size of heap for memsys3 or memsys5\n" #endif " -help show this message\n" " -html set output mode to HTML\n" " -interactive force interactive I/O\n" " -json set output mode to 'json'\n" " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n" " -markdown set output mode to 'markdown'\n" #if !defined(SQLITE_OMIT_DESERIALIZE) " -maxsize N maximum size for a --deserialize database\n" #endif " -memtrace trace all memory allocations and deallocations\n" " -mmap N default mmap size set to N\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif |
| ︙ | ︙ | |||
21202 21203 21204 21205 21206 21207 21208 |
zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
}else if( strcmp(z,"-zip")==0 ){
data.openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
| | | 22033 22034 22035 22036 22037 22038 22039 22040 22041 22042 22043 22044 22045 22046 22047 |
zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
}else if( strcmp(z,"-zip")==0 ){
data.openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
|
| ︙ | ︙ | |||
21319 21320 21321 21322 21323 21324 21325 |
memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
}else if( strcmp(z,"-zip")==0 ){
data.openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
| | | 22150 22151 22152 22153 22154 22155 22156 22157 22158 22159 22160 22161 22162 22163 22164 |
memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
}else if( strcmp(z,"-zip")==0 ){
data.openMode = SHELL_OPEN_ZIPFILE;
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
}else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
144 145 146 147 148 149 150 |
int argc,
sqlite3_value **argv
){
gather_artifact_stats(1);
}
/*
| | | | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
int argc,
sqlite3_value **argv
){
gather_artifact_stats(1);
}
/*
** Add the content(), compress(), decompress(), and
** gather_artifact_stats() SQL functions to database connection db.
*/
int add_content_sql_commands(sqlite3 *db){
sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
sqlcmd_content, 0, 0);
sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
sqlcmd_compress, 0, 0);
sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
|
| ︙ | ︙ | |||
169 170 171 172 173 174 175 | ** db_protect(X) ** db_protect_pop(X) ** ** These invoke the corresponding C routines. ** ** WARNING: ** Do not instantiate these functions for any Fossil webpage or command | | | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
** db_protect(X)
** db_protect_pop(X)
**
** These invoke the corresponding C routines.
**
** WARNING:
** Do not instantiate these functions for any Fossil webpage or command
** method other than the "fossil sql" command. If an attacker gains access
** to these functions, he will be able to disable other defense mechanisms.
**
** This routines are for interactiving testing only. They are experimental
** and undocumented (apart from this comments) and might go away or change
** in future releases.
**
** 2020-11-29: These functions are now only available if the "fossil sql"
** command is started with the --test option.
*/
static void sqlcmd_db_protect(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
|
| ︙ | ︙ | |||
203 204 205 206 207 208 209 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
if( !local_bSqlCmdTest ) db_protect_pop();
}
| < < < | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
if( !local_bSqlCmdTest ) db_protect_pop();
}
/*
** This is the "automatic extension" initializer that runs right after
** the connection to the repository database is opened. Set up the
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
sqlite3 *db,
|
| ︙ | ︙ | |||
227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
search_sql_setup(db);
foci_register(db);
deltafunc_init(db);
helptext_vtab_register(db);
builtin_vtab_register(db);
g.repositoryOpen = 1;
g.db = db;
sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
db_maybe_set_encryption_key(db, g.zRepositoryName);
if( g.zLocalDbName ){
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
g.zLocalDbName);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
| > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
search_sql_setup(db);
foci_register(db);
deltafunc_init(db);
helptext_vtab_register(db);
builtin_vtab_register(db);
g.repositoryOpen = 1;
g.db = db;
sqlite3_busy_timeout(db, 10000);
sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
db_maybe_set_encryption_key(db, g.zRepositoryName);
if( g.zLocalDbName ){
char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
g.zLocalDbName);
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
|
| ︙ | ︙ | |||
304 305 306 307 308 309 310 |
*pzKey = zKey;
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
*pnKey = (int)strlen(zKey);
}else{
*pnKey = -1;
}
}else{
| | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
*pzKey = zKey;
if( fossil_getenv("FOSSIL_USE_SEE_TEXTKEY")==0 ){
*pnKey = (int)strlen(zKey);
}else{
*pnKey = -1;
}
}else{
fossil_fatal("failed to allocate %u bytes for key", nByte);
}
}
#endif
/*
** This routine closes the Fossil databases and/or invalidates the global
** state variables that keep track of them.
|
| ︙ | ︙ |
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.36.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 |
| ︙ | ︙ | |||
79 80 81 82 83 84 85 | #endif #if SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif #if SQLITE_64BIT_STATS "64BIT_STATS", #endif | > | | > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #endif #if SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif #if SQLITE_64BIT_STATS "64BIT_STATS", #endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), # endif #endif #if SQLITE_ALLOW_URI_AUTHORITY "ALLOW_URI_AUTHORITY", #endif #ifdef SQLITE_BITMASK_TYPE "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE), #endif |
| ︙ | ︙ | |||
142 143 144 145 146 147 148 | #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #ifdef SQLITE_DEFAULT_LOOKASIDE "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), #endif | > | | > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif #ifdef SQLITE_DEFAULT_LOOKASIDE "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE), #endif #ifdef SQLITE_DEFAULT_MEMSTATUS # if SQLITE_DEFAULT_MEMSTATUS != 1 "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS), # endif #endif #ifdef SQLITE_DEFAULT_MMAP_SIZE "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), #endif #ifdef SQLITE_DEFAULT_PAGE_SIZE "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE), #endif |
| ︙ | ︙ | |||
217 218 219 220 221 222 223 | #endif #if SQLITE_ENABLE_BATCH_ATOMIC_WRITE "ENABLE_BATCH_ATOMIC_WRITE", #endif #if SQLITE_ENABLE_BYTECODE_VTAB "ENABLE_BYTECODE_VTAB", #endif | | > > > | | < < < | 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 | #endif #if SQLITE_ENABLE_BATCH_ATOMIC_WRITE "ENABLE_BATCH_ATOMIC_WRITE", #endif #if SQLITE_ENABLE_BYTECODE_VTAB "ENABLE_BYTECODE_VTAB", #endif #ifdef SQLITE_ENABLE_CEROD "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), #endif #if SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", #endif #if SQLITE_ENABLE_COLUMN_USED_MASK "ENABLE_COLUMN_USED_MASK", #endif #if SQLITE_ENABLE_COSTMULT "ENABLE_COSTMULT", #endif #if SQLITE_ENABLE_CURSOR_HINTS "ENABLE_CURSOR_HINTS", #endif #if SQLITE_ENABLE_DBPAGE_VTAB "ENABLE_DBPAGE_VTAB", #endif #if SQLITE_ENABLE_DBSTAT_VTAB "ENABLE_DBSTAT_VTAB", #endif #if SQLITE_ENABLE_EXPENSIVE_ASSERT "ENABLE_EXPENSIVE_ASSERT", #endif #if SQLITE_ENABLE_EXPLAIN_COMMENTS "ENABLE_EXPLAIN_COMMENTS", #endif #if SQLITE_ENABLE_FTS3 "ENABLE_FTS3", #endif #if SQLITE_ENABLE_FTS3_PARENTHESIS "ENABLE_FTS3_PARENTHESIS", #endif |
| ︙ | ︙ | |||
300 301 302 303 304 305 306 307 308 309 310 311 312 313 | "ENABLE_MULTIPLEX", #endif #if SQLITE_ENABLE_NORMALIZE "ENABLE_NORMALIZE", #endif #if SQLITE_ENABLE_NULL_TRIM "ENABLE_NULL_TRIM", #endif #if SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif #if SQLITE_ENABLE_PREUPDATE_HOOK "ENABLE_PREUPDATE_HOOK", #endif | > > > | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | "ENABLE_MULTIPLEX", #endif #if SQLITE_ENABLE_NORMALIZE "ENABLE_NORMALIZE", #endif #if SQLITE_ENABLE_NULL_TRIM "ENABLE_NULL_TRIM", #endif #if SQLITE_ENABLE_OFFSET_SQL_FUNC "ENABLE_OFFSET_SQL_FUNC", #endif #if SQLITE_ENABLE_OVERSIZE_CELL_CHECK "ENABLE_OVERSIZE_CELL_CHECK", #endif #if SQLITE_ENABLE_PREUPDATE_HOOK "ENABLE_PREUPDATE_HOOK", #endif |
| ︙ | ︙ | |||
331 332 333 334 335 336 337 | #endif #if SQLITE_ENABLE_SORTER_REFERENCES "ENABLE_SORTER_REFERENCES", #endif #if SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | #endif #if SQLITE_ENABLE_SORTER_REFERENCES "ENABLE_SORTER_REFERENCES", #endif #if SQLITE_ENABLE_SQLLOG "ENABLE_SQLLOG", #endif #if SQLITE_ENABLE_STAT4 "ENABLE_STAT4", #endif #if SQLITE_ENABLE_STMTVTAB "ENABLE_STMTVTAB", #endif #if SQLITE_ENABLE_STMT_SCANSTATUS "ENABLE_STMT_SCANSTATUS", |
| ︙ | ︙ | |||
385 386 387 388 389 390 391 | #endif #if SQLITE_FTS5_NO_WITHOUT_ROWID "FTS5_NO_WITHOUT_ROWID", #endif #if HAVE_ISNAN || SQLITE_HAVE_ISNAN "HAVE_ISNAN", #endif | > | | > | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | #endif #if SQLITE_FTS5_NO_WITHOUT_ROWID "FTS5_NO_WITHOUT_ROWID", #endif #if HAVE_ISNAN || SQLITE_HAVE_ISNAN "HAVE_ISNAN", #endif #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX # if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1 "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX), # endif #endif #if SQLITE_IGNORE_AFP_LOCK_ERRORS "IGNORE_AFP_LOCK_ERRORS", #endif #if SQLITE_IGNORE_FLOCK_LOCK_ERRORS "IGNORE_FLOCK_LOCK_ERRORS", #endif |
| ︙ | ︙ | |||
484 485 486 487 488 489 490 | #endif #if SQLITE_MMAP_READWRITE "MMAP_READWRITE", #endif #if SQLITE_MUTEX_NOOP "MUTEX_NOOP", #endif | < < < | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | #endif #if SQLITE_MMAP_READWRITE "MMAP_READWRITE", #endif #if SQLITE_MUTEX_NOOP "MUTEX_NOOP", #endif #if SQLITE_MUTEX_OMIT "MUTEX_OMIT", #endif #if SQLITE_MUTEX_PTHREADS "MUTEX_PTHREADS", #endif #if SQLITE_MUTEX_W32 |
| ︙ | ︙ | |||
556 557 558 559 560 561 562 | #endif #if SQLITE_OMIT_CONFLICT_CLAUSE "OMIT_CONFLICT_CLAUSE", #endif #if SQLITE_OMIT_CTE "OMIT_CTE", #endif | | > > > | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | #endif #if SQLITE_OMIT_CONFLICT_CLAUSE "OMIT_CONFLICT_CLAUSE", #endif #if SQLITE_OMIT_CTE "OMIT_CTE", #endif #if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT) "OMIT_DATETIME_FUNCS", #endif #if SQLITE_OMIT_DECLTYPE "OMIT_DECLTYPE", #endif #if SQLITE_OMIT_DEPRECATED "OMIT_DEPRECATED", #endif #if SQLITE_OMIT_DESERIALIZE "OMIT_DESERIALIZE", #endif #if SQLITE_OMIT_DISKIO "OMIT_DISKIO", #endif #if SQLITE_OMIT_EXPLAIN "OMIT_EXPLAIN", #endif |
| ︙ | ︙ | |||
591 592 593 594 595 596 597 598 599 600 601 602 603 604 | "OMIT_HEX_INTEGER", #endif #if SQLITE_OMIT_INCRBLOB "OMIT_INCRBLOB", #endif #if SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif #if SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif #if SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif | > > > | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | "OMIT_HEX_INTEGER", #endif #if SQLITE_OMIT_INCRBLOB "OMIT_INCRBLOB", #endif #if SQLITE_OMIT_INTEGRITY_CHECK "OMIT_INTEGRITY_CHECK", #endif #if SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif #if SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif #if SQLITE_OMIT_LOAD_EXTENSION "OMIT_LOAD_EXTENSION", #endif |
| ︙ | ︙ | |||
655 656 657 658 659 660 661 | #endif #if SQLITE_OMIT_TEMPDB "OMIT_TEMPDB", #endif #if SQLITE_OMIT_TEST_CONTROL "OMIT_TEST_CONTROL", #endif | > | | > | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 | #endif #if SQLITE_OMIT_TEMPDB "OMIT_TEMPDB", #endif #if SQLITE_OMIT_TEST_CONTROL "OMIT_TEST_CONTROL", #endif #ifdef SQLITE_OMIT_TRACE # if SQLITE_OMIT_TRACE != 1 "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE), # endif #endif #if SQLITE_OMIT_TRIGGER "OMIT_TRIGGER", #endif #if SQLITE_OMIT_TRUNCATE_OPTIMIZATION "OMIT_TRUNCATE_OPTIMIZATION", #endif |
| ︙ | ︙ | |||
691 692 693 694 695 696 697 | #endif #if SQLITE_PCACHE_SEPARATE_HEADER "PCACHE_SEPARATE_HEADER", #endif #if SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif | > | | > | 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | #endif #if SQLITE_PCACHE_SEPARATE_HEADER "PCACHE_SEPARATE_HEADER", #endif #if SQLITE_PERFORMANCE_TRACE "PERFORMANCE_TRACE", #endif #ifdef SQLITE_POWERSAFE_OVERWRITE # if SQLITE_POWERSAFE_OVERWRITE != 1 "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE), # endif #endif #if SQLITE_PREFER_PROXY_LOCKING "PREFER_PROXY_LOCKING", #endif #if SQLITE_PROXY_DEBUG "PROXY_DEBUG", #endif |
| ︙ | ︙ | |||
727 728 729 730 731 732 733 | #endif #ifdef SQLITE_STMTJRNL_SPILL "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL), #endif #if SQLITE_SUBSTR_COMPATIBILITY "SUBSTR_COMPATIBILITY", #endif | > > > | | 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 |
#endif
#ifdef SQLITE_STMTJRNL_SPILL
"STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
#endif
#if SQLITE_SUBSTR_COMPATIBILITY
"SUBSTR_COMPATIBILITY",
#endif
#if (!defined(SQLITE_WIN32_MALLOC) \
&& !defined(SQLITE_ZERO_MALLOC) \
&& !defined(SQLITE_MEMDEBUG) \
) || defined(SQLITE_SYSTEM_MALLOC)
"SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
"TCL",
#endif
#ifdef SQLITE_TEMP_STORE
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
| ︙ | ︙ | |||
1182 1183 1184 1185 1186 1187 1188 | ** 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()]. */ | | | | | 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 | ** 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.36.0" #define SQLITE_VERSION_NUMBER 3036000 #define SQLITE_SOURCE_ID "2021-06-07 00:41:18 2aa9368b63b42ac7c700516f109edcc6098c12b850eae591afed4e51a3f41819" /* ** 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 |
| ︙ | ︙ | |||
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 | ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 | > > > > > > > > > > > > > > > > > | 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 | ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** </ul> ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode ** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that ** currently has an SQL transaction open on the database. It is set to 0 if ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes. ** </ul> ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]] ** Used by the cksmvfs VFS module only. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| ︙ | ︙ | |||
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 | #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 #define SQLITE_FCNTL_CKPT_DONE 37 #define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_CKPT_START 39 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO | > > | 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 | #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 #define SQLITE_FCNTL_CKPT_DONE 37 #define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_CKPT_START 39 #define SQLITE_FCNTL_EXTERNAL_READER 40 #define SQLITE_FCNTL_CKSM_FILE 41 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| ︙ | ︙ | |||
5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 | ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement ** METHOD: sqlite3_stmt ** | > > > > > > > > > | 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 | ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. ** ** ^This routine returns false if there is any possibility that the ** statement might change the database file. ^A false return does ** not guarantee that the statement will change the database file. ** ^For example, an UPDATE statement might have a WHERE clause that ** makes it a no-op, but the sqlite3_stmt_readonly() result would still ** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a ** read-only no-op if the table already exists, but ** sqlite3_stmt_readonly() still returns false for such a statement. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement ** METHOD: sqlite3_stmt ** |
| ︙ | ︙ | |||
5407 5408 5409 5410 5411 5412 5413 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** | | | > | | | | < | | > > > | < | > > | 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. ** ^These three options exist: ** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. ** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is ** bound to something else, whichever occurs sooner. ** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the ** object is to be copied prior to the return from sqlite3_bind_*(). ^The ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If ** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior |
| ︙ | ︙ | |||
6160 6161 6162 6163 6164 6165 6166 | ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** | < < | 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 | ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** all application-defined SQL functions that do not need to be ** used inside of triggers, view, CHECK constraints, or other elements of ** the database schema. This flags is especially recommended for SQL ** functions that have side effects or reveal internal application state. ** Without this flag, an attacker might be able to modify the schema of ** a database file to include invocations of the function with parameters ** chosen by the attacker, which the application will then execute when ** the database file is opened and read. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters passed to the three ** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or |
| ︙ | ︙ | |||
8838 8839 8840 8841 8842 8843 8844 | #define SQLITE_TESTCTRL_IMPOSTER 25 #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 | > | | 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 | #define SQLITE_TESTCTRL_IMPOSTER 25 #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_LAST 32 /* 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, |
| ︙ | ︙ | |||
10590 10591 10592 10593 10594 10595 10596 10597 10598 10599 10600 10601 10602 10603 10604 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 |
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#endif
/*
** CAPI3REF: Low-level system error code
** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
| > > > > > > > > > > | 10640 10641 10642 10643 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 10659 10660 10661 10662 10663 10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 10674 10675 10676 10677 10678 10679 10680 10681 10682 10683 |
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** When the [sqlite3_blob_write()] API is used to update a blob column,
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
** in this case the new values are not available. In this case, when a
** callback made with op==SQLITE_DELETE is actuall a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
** pre-update hook is being invoked for some other reason, including a
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif
/*
** CAPI3REF: Low-level system error code
** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
|
| ︙ | ︙ | |||
10848 10849 10850 10851 10852 10853 10854 | ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. ** | | | | 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922 10923 | ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API unsigned char *sqlite3_serialize( sqlite3 *db, /* The database connection */ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ ); |
| ︙ | ︙ | |||
10900 10901 10902 10903 10904 10905 10906 | ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** | | | | 10960 10961 10962 10963 10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974 10975 | ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API int sqlite3_deserialize( sqlite3 *db, /* The database connection */ const char *zSchema, /* Which DB to reopen with the deserialization */ unsigned char *pData, /* The serialized database content */ sqlite3_int64 szDb, /* Number bytes in the deserialization */ sqlite3_int64 szBuf, /* Total size of buffer pData[] */ |
| ︙ | ︙ | |||
11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 11162 11163 | ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object ** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 11210 11211 11212 11213 11214 11215 11216 11217 11218 11219 11220 11221 11222 11223 11224 11225 11226 11227 11228 11229 11230 11231 11232 11233 11234 11235 11236 11237 11238 11239 11240 11241 11242 11243 11244 11245 11246 11247 11248 11249 11250 11251 11252 11253 11254 11255 | ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPIREF: Conigure a Session Object ** METHOD: sqlite3_session ** ** This method is used to configure a session object after it has been ** created. At present the only valid value for the second parameter is ** [SQLITE_SESSION_OBJCONFIG_SIZE]. ** ** Arguments for sqlite3session_object_config() ** ** The following values may passed as the the 4th parameter to ** sqlite3session_object_config(). ** ** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd> ** This option is used to set, clear or query the flag that enables ** the [sqlite3session_changeset_size()] API. Because it imposes some ** computational overhead, this API is disabled by default. Argument ** pArg must point to a value of type (int). If the value is initially ** 0, then the sqlite3session_changeset_size() API is disabled. If it ** is greater than 0, then the same API is enabled. Or, if the initial ** value is less than zero, no change is made. In all cases the (int) ** variable is set to 1 if the sqlite3session_changeset_size() API is ** enabled following the current call, or 0 otherwise. ** ** It is an error (SQLITE_MISUSE) to attempt to modify this setting after ** the first table has been attached to the session object. */ SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); /* */ #define SQLITE_SESSION_OBJCONFIG_SIZE 1 /* ** CAPI3REF: Enable Or Disable A Session Object ** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When |
| ︙ | ︙ | |||
11394 11395 11396 11397 11398 11399 11400 11401 11402 11403 11404 11405 11406 11407 | */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Load The Difference Between Tables Into A Session ** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it | > > > > > > > > > > > > > > > > | 11486 11487 11488 11489 11490 11491 11492 11493 11494 11495 11496 11497 11498 11499 11500 11501 11502 11503 11504 11505 11506 11507 11508 11509 11510 11511 11512 11513 11514 11515 | */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Return An Upper-limit For The Size Of The Changeset ** METHOD: sqlite3_session ** ** By default, this function always returns 0. For it to return ** a useful result, the sqlite3_session object must have been configured ** to enable this API using sqlite3session_object_config() with the ** SQLITE_SESSION_OBJCONFIG_SIZE verb. ** ** When enabled, this function returns an upper limit, in bytes, for the size ** of the changeset that might be produced if sqlite3session_changeset() were ** called. The final changeset size might be equal to or smaller than the ** size in bytes returned by this function. */ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); /* ** CAPI3REF: Load The Difference Between Tables Into A Session ** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it |
| ︙ | ︙ | |||
14218 14219 14220 14221 14222 14223 14224 | #define TK_TRUTH 174 #define TK_REGISTER 175 #define TK_VECTOR 176 #define TK_SELECT_COLUMN 177 #define TK_IF_NULL_ROW 178 #define TK_ASTERISK 179 #define TK_SPAN 180 | > | | | 14326 14327 14328 14329 14330 14331 14332 14333 14334 14335 14336 14337 14338 14339 14340 14341 14342 | #define TK_TRUTH 174 #define TK_REGISTER 175 #define TK_VECTOR 176 #define TK_SELECT_COLUMN 177 #define TK_IF_NULL_ROW 178 #define TK_ASTERISK 179 #define TK_SPAN 180 #define TK_ERROR 181 #define TK_SPACE 182 #define TK_ILLEGAL 183 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> |
| ︙ | ︙ | |||
15756 15757 15758 15759 15760 15761 15762 | #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ #define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ #define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ #define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ #define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ #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] */ | | | 15865 15866 15867 15868 15869 15870 15871 15872 15873 15874 15875 15876 15877 15878 15879 | #define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */ #define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */ #define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */ #define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */ #define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */ #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_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */ #define OP_IncrVacuum 60 /* jump */ #define OP_VNext 61 /* jump */ #define OP_Init 62 /* jump, synopsis: Start at P2 */ #define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Function 64 /* synopsis: r[P3]=func(r[P2@NP]) */ #define OP_Return 65 |
| ︙ | ︙ | |||
15787 15788 15789 15790 15791 15792 15793 | #define OP_CollSeq 82 #define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */ #define OP_RealAffinity 84 #define OP_Cast 85 /* synopsis: affinity(r[P1]) */ #define OP_Permutation 86 #define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */ #define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ | > | | | | | | | | | | | < | | > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | 15896 15897 15898 15899 15900 15901 15902 15903 15904 15905 15906 15907 15908 15909 15910 15911 15912 15913 15914 15915 15916 15917 15918 15919 15920 15921 15922 15923 15924 15925 15926 15927 15928 15929 15930 15931 15932 15933 15934 15935 15936 15937 15938 15939 15940 15941 15942 15943 15944 15945 15946 15947 15948 15949 15950 15951 15952 15953 15954 15955 15956 15957 15958 15959 15960 15961 15962 15963 15964 15965 15966 15967 15968 15969 15970 15971 15972 15973 15974 15975 15976 15977 15978 15979 15980 15981 15982 15983 15984 15985 15986 15987 15988 15989 15990 15991 15992 15993 15994 15995 15996 15997 15998 15999 16000 | #define OP_CollSeq 82 #define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */ #define OP_RealAffinity 84 #define OP_Cast 85 /* synopsis: affinity(r[P1]) */ #define OP_Permutation 86 #define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */ #define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ #define OP_ZeroOrNull 89 /* synopsis: r[P2] = 0 OR NULL */ #define OP_Offset 90 /* synopsis: r[P3] = sqlite_offset(P1) */ #define OP_Column 91 /* synopsis: r[P3]=PX */ #define OP_Affinity 92 /* synopsis: affinity(r[P1@P2]) */ #define OP_MakeRecord 93 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ #define OP_Count 94 /* synopsis: r[P2]=count() */ #define OP_ReadCookie 95 #define OP_SetCookie 96 #define OP_ReopenIdx 97 /* synopsis: root=P2 iDb=P3 */ #define OP_OpenRead 98 /* synopsis: root=P2 iDb=P3 */ #define OP_OpenWrite 99 /* synopsis: root=P2 iDb=P3 */ #define OP_OpenDup 100 #define OP_OpenAutoindex 101 /* synopsis: nColumn=P2 */ #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_OpenEphemeral 112 /* synopsis: nColumn=P2 */ #define OP_BitNot 113 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ #define OP_SorterOpen 114 #define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ #define OP_String8 116 /* same as TK_STRING, synopsis: r[P2]='P4' */ #define OP_OpenPseudo 117 /* synopsis: P3 columns in r[P2] */ #define OP_Close 118 #define OP_ColumnsUsed 119 #define OP_SeekScan 120 /* synopsis: Scan-ahead up to P1 rows */ #define OP_SeekHit 121 /* synopsis: set P2<=seekHit<=P3 */ #define OP_Sequence 122 /* synopsis: r[P2]=cursor[P1].ctr++ */ #define OP_NewRowid 123 /* synopsis: r[P2]=rowid */ #define OP_Insert 124 /* synopsis: intkey=r[P3] data=r[P2] */ #define OP_RowCell 125 #define OP_Delete 126 #define OP_ResetCount 127 #define OP_SorterCompare 128 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ #define OP_SorterData 129 /* synopsis: r[P2]=data */ #define OP_RowData 130 /* synopsis: r[P2]=data */ #define OP_Rowid 131 /* synopsis: r[P2]=rowid */ #define OP_NullRow 132 #define OP_SeekEnd 133 #define OP_IdxInsert 134 /* synopsis: key=r[P2] */ #define OP_SorterInsert 135 /* synopsis: key=r[P2] */ #define OP_IdxDelete 136 /* synopsis: key=r[P2@P3] */ #define OP_DeferredSeek 137 /* synopsis: Move P3 to P1.rowid if needed */ #define OP_IdxRowid 138 /* synopsis: r[P2]=rowid */ #define OP_FinishSeek 139 #define OP_Destroy 140 #define OP_Clear 141 #define OP_ResetSorter 142 #define OP_CreateBtree 143 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ #define OP_SqlExec 144 #define OP_ParseSchema 145 #define OP_LoadAnalysis 146 #define OP_DropTable 147 #define OP_DropIndex 148 #define OP_DropTrigger 149 #define OP_IntegrityCk 150 #define OP_RowSetAdd 151 /* synopsis: rowset(P1)=r[P2] */ #define OP_Real 152 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ #define OP_Param 153 #define OP_FkCounter 154 /* synopsis: fkctr[P1]+=P2 */ #define OP_MemMax 155 /* synopsis: r[P1]=max(r[P1],r[P2]) */ #define OP_OffsetLimit 156 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ #define OP_AggInverse 157 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ #define OP_AggStep 158 /* synopsis: accum=r[P3] step(r[P2@P5]) */ #define OP_AggStep1 159 /* synopsis: accum=r[P3] step(r[P2@P5]) */ #define OP_AggValue 160 /* synopsis: r[P3]=value N=P2 */ #define OP_AggFinal 161 /* synopsis: accum=r[P1] N=P2 */ #define OP_Expire 162 #define OP_CursorLock 163 #define OP_CursorUnlock 164 #define OP_TableLock 165 /* synopsis: iDb=P1 root=P2 write=P3 */ #define OP_VBegin 166 #define OP_VCreate 167 #define OP_VDestroy 168 #define OP_VOpen 169 #define OP_VColumn 170 /* synopsis: r[P3]=vcolumn(P2) */ #define OP_VRename 171 #define OP_Pagecount 172 #define OP_MaxPgcnt 173 #define OP_Trace 174 #define OP_CursorHint 175 #define OP_ReleaseReg 176 /* synopsis: release r[P1@P2] mask P3 */ #define OP_Noop 177 #define OP_Explain 178 #define OP_Abortable 179 /* 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 */ |
| ︙ | ︙ | |||
15900 15901 15902 15903 15904 15905 15906 | /* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ /* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\ /* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\ /* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\ /* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ /* 80 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ | | | | | | | | | | | 16010 16011 16012 16013 16014 16015 16016 16017 16018 16019 16020 16021 16022 16023 16024 16025 16026 16027 16028 16029 16030 16031 16032 16033 16034 16035 16036 16037 | /* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ /* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\ /* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\ /* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\ /* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\ /* 80 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ /* 88 */ 0x12, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10,\ /* 96 */ 0x00, 0x00, 0x00, 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, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\ /* 128 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04,\ /* 136 */ 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x10,\ /* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\ /* 152 */ 0x10, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00,\ /* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ /* 176 */ 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 62 /* Maximum JUMP opcode */ |
| ︙ | ︙ | |||
17003 17004 17005 17006 17007 17008 17009 |
struct sqlite3InitInfo { /* Information used during initialization */
Pgno newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
| < < < | 17113 17114 17115 17116 17117 17118 17119 17120 17121 17122 17123 17124 17125 17126 17127 |
struct sqlite3InitInfo { /* Information used during initialization */
Pgno newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
int nVdbeWrite; /* Number of active VDBEs that read and write */
int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
|
| ︙ | ︙ | |||
17204 17205 17206 17207 17208 17209 17210 | #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */ #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 */ | | | 17311 17312 17313 17314 17315 17316 17317 17318 17319 17320 17321 17322 17323 17324 17325 | #define SQLITE_Stat4 0x00000800 /* Use STAT4 data */ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */ #define SQLITE_PushDown 0x00001000 /* The push-down optimization */ #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_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) |
| ︙ | ︙ | |||
17577 17578 17579 17580 17581 17582 17583 | ** changing the affinity. ** ** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. ** It causes an assert() to fire if either operand to a comparison ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ | < < | 17684 17685 17686 17687 17688 17689 17690 17691 17692 17693 17694 17695 17696 17697 17698 | ** changing the affinity. ** ** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL. ** It causes an assert() to fire if either operand to a comparison ** operator is NULL. It is added to certain comparison operators to ** prove that the operands are always NOT NULL. */ #define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */ #define SQLITE_NULLEQ 0x80 /* NULL=NULL */ #define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */ /* ** An object of this type is created for each virtual table present in ** the database schema. ** |
| ︙ | ︙ | |||
17711 17712 17713 17714 17715 17716 17717 17718 17719 17720 17721 17722 17723 17724 |
** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
#define TF_Ephemeral 0x4000 /* An ephemeral table */
/*
** Test to see whether or not a table is a virtual table. This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
| > | 17816 17817 17818 17819 17820 17821 17822 17823 17824 17825 17826 17827 17828 17829 17830 |
** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
#define TF_Ephemeral 0x4000 /* An ephemeral table */
#define TF_Eponymous 0x8000 /* An eponymous virtual table */
/*
** Test to see whether or not a table is a virtual table. This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
| ︙ | ︙ | |||
18076 18077 18078 18079 18080 18081 18082 18083 18084 18085 18086 18087 18088 18089 |
** Additional columns are used only as parameters to
** aggregate functions */
struct AggInfo_func { /* For each aggregate function */
Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
};
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
| > | 18182 18183 18184 18185 18186 18187 18188 18189 18190 18191 18192 18193 18194 18195 18196 |
** Additional columns are used only as parameters to
** aggregate functions */
struct AggInfo_func { /* For each aggregate function */
Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
int iDistAddr; /* Address of OP_OpenEphemeral */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
};
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
|
| ︙ | ︙ | |||
18348 18349 18350 18351 18352 18353 18354 18355 18356 18357 18358 18359 18360 18361 |
** of subqueries
**
** ENAME_SPAN Text of the original result set
** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
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 */
| > | 18455 18456 18457 18458 18459 18460 18461 18462 18463 18464 18465 18466 18467 18468 18469 |
** of subqueries
**
** ENAME_SPAN Text of the original result set
** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
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 */
|
| ︙ | ︙ | |||
18421 18422 18423 18424 18425 18426 18427 18428 18429 18430 18431 18432 18433 18434 |
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
| > | 18529 18530 18531 18532 18533 18534 18535 18536 18537 18538 18539 18540 18541 18542 18543 |
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_schema */
unsigned isCte :1; /* This is a CTE */
unsigned notCte :1; /* This item may not match a CTE */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
| ︙ | ︙ | |||
18492 18493 18494 18495 18496 18497 18498 |
#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of
** the OR optimization */
#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
| | | 18601 18602 18603 18604 18605 18606 18607 18608 18609 18610 18611 18612 18613 18614 18615 |
#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of
** the OR optimization */
#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
/* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
/* Allowed return values from sqlite3WhereIsDistinct()
|
| ︙ | ︙ | |||
18538 18539 18540 18541 18542 18543 18544 |
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
| | | 18647 18648 18649 18650 18651 18652 18653 18654 18655 18656 18657 18658 18659 18660 18661 |
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
/*
** Allowed values for the NameContext, ncFlags field.
**
|
| ︙ | ︙ | |||
18571 18572 18573 18574 18575 18576 18577 18578 18579 18580 18581 18582 18583 18584 | #define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x02000 /* True if a function or subquery seen */ #define NC_AllowWin 0x04000 /* Window functions are allowed here */ #define NC_HasWin 0x08000 /* One or more window functions seen */ #define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */ #define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */ /* ** An instance of the following object describes a single ON CONFLICT ** clause in an upsert. ** ** The pUpsertTarget field is only set if the ON CONFLICT clause includes ** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the | > | 18680 18681 18682 18683 18684 18685 18686 18687 18688 18689 18690 18691 18692 18693 18694 | #define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x02000 /* True if a function or subquery seen */ #define NC_AllowWin 0x04000 /* Window functions are allowed here */ #define NC_HasWin 0x08000 /* One or more window functions seen */ #define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */ #define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */ #define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */ #define NC_NoSelect 0x80000 /* Do not descend into sub-selects */ /* ** An instance of the following object describes a single ON CONFLICT ** clause in an upsert. ** ** The pUpsertTarget field is only set if the ON CONFLICT clause includes ** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the |
| ︙ | ︙ | |||
19211 19212 19213 19214 19215 19216 19217 19218 19219 19220 19221 19222 19223 19224 |
/*
** Allowed values for mInitFlags
*/
#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
| > > > > > > > > > > > > > > > > | 19321 19322 19323 19324 19325 19326 19327 19328 19329 19330 19331 19332 19333 19334 19335 19336 19337 19338 19339 19340 19341 19342 19343 19344 19345 19346 19347 19348 19349 19350 |
/*
** 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.
**
** Tuning parameters are numbered starting with 1.
*/
#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */
#ifdef SQLITE_DEBUG
# define Tuning(X) (sqlite3Config.aTune[(X)-1])
#else
# define Tuning(X) 0
#endif
/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
int bMemstat; /* True to enable memory status */
|
| ︙ | ︙ | |||
19265 19266 19267 19268 19269 19270 19271 | #ifdef SQLITE_VDBE_COVERAGE /* The following callback (if not NULL) is invoked on every VDBE branch ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. */ void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ void *pVdbeBranchArg; /* 1st argument */ #endif | | > > > > | 19391 19392 19393 19394 19395 19396 19397 19398 19399 19400 19401 19402 19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 19417 19418 | #ifdef SQLITE_VDBE_COVERAGE /* The following callback (if not NULL) is invoked on every VDBE branch ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE. */ void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */ void *pVdbeBranchArg; /* 1st argument */ #endif #ifndef SQLITE_OMIT_DESERIALIZE sqlite3_int64 mxMemdbSize; /* Default max memdb size */ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ /* vvvv--- must be last ---vvv */ #ifdef SQLITE_DEBUG sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */ #endif }; /* ** This macro is used inside of assert() statements to indicate that ** the assert is only valid on a well-formed database. Instead of: ** ** assert( X ); |
| ︙ | ︙ | |||
19352 19353 19354 19355 19356 19357 19358 19359 19360 19361 19362 19363 19364 19365 19366 19367 19368 19369 | SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*); SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); #endif /* ** Return code from the parse-tree walking primitives and their ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ | > > > > > > > | 19482 19483 19484 19485 19486 19487 19488 19489 19490 19491 19492 19493 19494 19495 19496 19497 19498 19499 19500 19501 19502 19503 19504 19505 19506 | SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*); SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*); SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*); SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*); SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*); SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*); SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*); #ifdef SQLITE_DEBUG SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*); #endif #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*); #else # define sqlite3SelectPopWith 0 #endif /* ** Return code from the parse-tree walking primitives and their ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ |
| ︙ | ︙ | |||
19390 19391 19392 19393 19394 19395 19396 19397 19398 19399 19400 19401 19402 19403 |
/*
** An instance of the With object represents a WITH clause containing
** one or more CTEs (common table expressions).
*/
struct With {
int nCte; /* Number of CTEs in the WITH clause */
With *pOuter; /* Containing WITH clause, or NULL */
Cte a[1]; /* For each CTE in the WITH clause.... */
};
/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation. (The query flattener or other parser tree
| > | 19527 19528 19529 19530 19531 19532 19533 19534 19535 19536 19537 19538 19539 19540 19541 |
/*
** An instance of the With object represents a WITH clause containing
** one or more CTEs (common table expressions).
*/
struct With {
int nCte; /* Number of CTEs in the WITH clause */
int bView; /* Belongs to the outermost Select of a view */
With *pOuter; /* Containing WITH clause, or NULL */
Cte a[1]; /* For each CTE in the WITH clause.... */
};
/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation. (The query flattener or other parser tree
|
| ︙ | ︙ | |||
19760 19761 19762 19763 19764 19765 19766 19767 19768 19769 19770 19771 19772 19773 | SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); | > | 19898 19899 19900 19901 19902 19903 19904 19905 19906 19907 19908 19909 19910 19911 19912 | SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*); SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*); SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*); SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*); SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*); SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int); SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); |
| ︙ | ︙ | |||
19781 19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 | SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); #endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16); #ifdef SQLITE_OMIT_GENERATED_COLUMNS | > | 19920 19921 19922 19923 19924 19925 19926 19927 19928 19929 19930 19931 19932 19933 19934 | SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); #endif SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*); SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect); SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**); SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char); SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int); SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*); SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16); #ifdef SQLITE_OMIT_GENERATED_COLUMNS |
| ︙ | ︙ | |||
20159 20160 20161 20162 20163 20164 20165 | SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); #if defined(SQLITE_NEED_ERR_NAME) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif | | | 20299 20300 20301 20302 20303 20304 20305 20306 20307 20308 20309 20310 20311 20312 20313 | SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); #if defined(SQLITE_NEED_ERR_NAME) SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif #ifndef SQLITE_OMIT_DESERIALIZE SQLITE_PRIVATE int sqlite3MemdbInit(void); #endif SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*); |
| ︙ | ︙ | |||
20210 20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 | #endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; SQLITE_PRIVATE const char sqlite3StrBINARY[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte; #endif #endif /* SQLITE_AMALGAMATION */ | > > > | 20350 20351 20352 20353 20354 20355 20356 20357 20358 20359 20360 20361 20362 20363 20364 20365 20366 | #endif SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[]; SQLITE_PRIVATE const char sqlite3StrBINARY[]; SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[]; SQLITE_PRIVATE const unsigned char *sqlite3aLTb; SQLITE_PRIVATE const unsigned char *sqlite3aEQb; SQLITE_PRIVATE const unsigned char *sqlite3aGTb; SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[]; SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config; SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; #ifndef SQLITE_OMIT_WSD SQLITE_PRIVATE int sqlite3PendingByte; #endif #endif /* SQLITE_AMALGAMATION */ |
| ︙ | ︙ | |||
20676 20677 20678 20679 20680 20681 20682 |
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,
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 20819 20820 20821 20822 20823 20824 20825 20826 20827 20828 20829 20830 20831 20832 20833 20834 20835 20836 20837 20838 20839 20840 20841 20842 20843 20844 20845 20846 20847 20848 20849 20850 20851 20852 20853 20854 20855 20856 20857 20858 20859 20860 20861 20862 20863 20864 20865 20866 20867 20868 20869 20870 20871 20872 20873 20874 20875 20876 20877 20878 20879 20880 20881 |
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,
#endif
#ifdef SQLITE_EBCDIC
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
/* All of the upper-to-lower conversion data is above. The following
** 18 integers are completely unrelated. They are appended to the
** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
** going on:
**
** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
** by invoking sqlite3MemCompare(A,B) which compares values A and B and
** returns negative, zero, or positive if A is less then, equal to, or
** greater than B, respectively. Then the true false results is found by
** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
** is negative, zero, or positive, where opcode is the specific opcode.
** The only works because the comparison opcodes are consecutive and in
** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
** ensure that is the case.
**
** These elements must be appended to another array. Otherwise the
** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
** be undefined behavior. That's goofy, but the C-standards people thought
** it was a good idea, so here we are.
*/
/* NE EQ GT LE LT GE */
1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
};
SQLITE_PRIVATE const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
SQLITE_PRIVATE const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
/*
** The following 256 byte lookup table is used to support SQLites built-in
** equivalents to the following standard library functions:
**
** isspace() 0x01
** isalpha() 0x02
|
| ︙ | ︙ | |||
20890 20891 20892 20893 20894 20895 20896 | 0, /* xSqllog */ 0, /* pSqllogArg */ #endif #ifdef SQLITE_VDBE_COVERAGE 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif | | | 21061 21062 21063 21064 21065 21066 21067 21068 21069 21070 21071 21072 21073 21074 21075 | 0, /* xSqllog */ 0, /* pSqllogArg */ #endif #ifdef SQLITE_VDBE_COVERAGE 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif #ifndef SQLITE_OMIT_DESERIALIZE SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ 0x7ffffffe, /* iOnceResetThreshold */ |
| ︙ | ︙ | |||
21453 21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 21465 21466 | VdbeCursor *pCsr; /* Cursor to read old values from */ int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; | > | 21624 21625 21626 21627 21628 21629 21630 21631 21632 21633 21634 21635 21636 21637 21638 | VdbeCursor *pCsr; /* Cursor to read old values from */ int op; /* One of SQLITE_INSERT, UPDATE, DELETE */ u8 *aRecord; /* old.* database record */ KeyInfo keyinfo; UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */ UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */ int iNewReg; /* Register for new.* values */ int iBlobWrite; /* Value returned by preupdate_blobwrite() */ i64 iKey1; /* First key value passed to hook */ i64 iKey2; /* Second key value passed to hook */ Mem *aNew; /* Array of new.* values */ Table *pTab; /* Schema object being upated */ Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; |
| ︙ | ︙ | |||
21541 21542 21543 21544 21545 21546 21547 | #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*); #endif SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *); #ifdef SQLITE_ENABLE_PREUPDATE_HOOK | | > | 21713 21714 21715 21716 21717 21718 21719 21720 21721 21722 21723 21724 21725 21726 21727 21728 |
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*);
#endif
SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
| ︙ | ︙ | |||
23469 23470 23471 23472 23473 23474 23475 |
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
| | | 23642 23643 23644 23645 23646 23647 23648 23649 23650 23651 23652 23653 23654 23655 23656 |
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3OsAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
|
| ︙ | ︙ | |||
27759 27760 27761 27762 27763 27764 27765 |
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
int rc;
if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
| < | 27932 27933 27934 27935 27936 27937 27938 27939 27940 27941 27942 27943 27944 27945 |
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
int rc;
if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|| sqlite3GlobalConfig.nPage<=0 ){
sqlite3GlobalConfig.pPage = 0;
sqlite3GlobalConfig.szPage = 0;
}
rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
| ︙ | ︙ | |||
28458 28459 28460 28461 28462 28463 28464 |
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
| | | 28630 28631 28632 28633 28634 28635 28636 28637 28638 28639 28640 28641 28642 28643 28644 |
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
#define etSRCITEM 12 /* a pointer to a SrcItem */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
#define etINVALID 17 /* Any unrecognized conversion type */
|
| ︙ | ︙ | |||
28524 28525 28526 28527 28528 28529 28530 |
{ 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
| | > > > > > > | 28696 28697 28698 28699 28700 28701 28702 28703 28704 28705 28706 28707 28708 28709 28710 28711 28712 28713 28714 28715 28716 28717 28718 |
{ 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
{ 'S', 0, 0, etSRCITEM, 0, 0 },
{ 'r', 10, 1, etORDINAL, 0, 0 },
};
/* Notes:
**
** %S Takes a pointer to SrcItem. Shows name or database.name
** %!S Like %S but prefer the zName over the zAlias
*/
/* Floating point constants used for rounding */
static const double arRound[] = {
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
};
|
| ︙ | ︙ | |||
29282 29283 29284 29285 29286 29287 29288 |
assert( bArgList==0 );
if( pToken && pToken->n ){
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
}
length = width = 0;
break;
}
| | < < | < < < > > > | | | | | > > > > > | 29460 29461 29462 29463 29464 29465 29466 29467 29468 29469 29470 29471 29472 29473 29474 29475 29476 29477 29478 29479 29480 29481 29482 29483 29484 29485 29486 29487 29488 29489 29490 29491 |
assert( bArgList==0 );
if( pToken && pToken->n ){
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
}
length = width = 0;
break;
}
case etSRCITEM: {
SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
pItem = va_arg(ap, SrcItem*);
assert( bArgList==0 );
if( pItem->zAlias && !flag_altform2 ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else if( pItem->zName ){
if( pItem->zDatabase ){
sqlite3_str_appendall(pAccum, pItem->zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else if( ALWAYS(pItem->pSelect) ){
sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
}
length = width = 0;
break;
}
default: {
assert( xtype==etINVALID );
return;
}
|
| ︙ | ︙ | |||
29876 29877 29878 29879 29880 29881 29882 |
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
for(i=0; i<pSrc->nSrc; i++){
const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
| > | < < < < < < < < | 30057 30058 30059 30060 30061 30062 30063 30064 30065 30066 30067 30068 30069 30070 30071 30072 30073 30074 30075 30076 |
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
for(i=0; i<pSrc->nSrc; i++){
const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
if( pItem->pTab ){
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
}
if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
}
if( pItem->fg.fromDDL ){
sqlite3_str_appendf(&x, " DDL");
}
if( pItem->fg.isCte ){
|
| ︙ | ︙ | |||
30454 30455 30456 30457 30458 30459 30460 30461 30462 30463 30464 30465 30466 30467 |
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;
}
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
| > > > > > > > > | 30628 30629 30630 30631 30632 30633 30634 30635 30636 30637 30638 30639 30640 30641 30642 30643 30644 30645 30646 30647 30648 30649 |
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;
}
case TK_ERROR: {
Expr tmp;
sqlite3TreeViewLine(pView, "ERROR");
tmp = *pExpr;
tmp.op = pExpr->op2;
sqlite3TreeViewExpr(pView, &tmp, 0);
break;
}
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
|
| ︙ | ︙ | |||
33528 33529 33530 33531 33532 33533 33534 |
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
/* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
/* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
| | | 33710 33711 33712 33713 33714 33715 33716 33717 33718 33719 33720 33721 33722 33723 33724 |
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
/* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
/* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 58 */ "ElseEq" OpHelp(""),
/* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 60 */ "IncrVacuum" OpHelp(""),
/* 61 */ "VNext" OpHelp(""),
/* 62 */ "Init" OpHelp("Start at P2"),
/* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
/* 64 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
/* 65 */ "Return" OpHelp(""),
|
| ︙ | ︙ | |||
33559 33560 33561 33562 33563 33564 33565 |
/* 82 */ "CollSeq" OpHelp(""),
/* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
/* 84 */ "RealAffinity" OpHelp(""),
/* 85 */ "Cast" OpHelp("affinity(r[P1])"),
/* 86 */ "Permutation" OpHelp(""),
/* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
| > | | | | | | | | | | | | < | > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | 33741 33742 33743 33744 33745 33746 33747 33748 33749 33750 33751 33752 33753 33754 33755 33756 33757 33758 33759 33760 33761 33762 33763 33764 33765 33766 33767 33768 33769 33770 33771 33772 33773 33774 33775 33776 33777 33778 33779 33780 33781 33782 33783 33784 33785 33786 33787 33788 33789 33790 33791 33792 33793 33794 33795 33796 33797 33798 33799 33800 33801 33802 33803 33804 33805 33806 33807 33808 33809 33810 33811 33812 33813 33814 33815 33816 33817 33818 33819 33820 33821 33822 33823 33824 33825 33826 33827 33828 33829 33830 33831 33832 33833 33834 33835 33836 33837 33838 33839 33840 33841 33842 33843 33844 33845 |
/* 82 */ "CollSeq" OpHelp(""),
/* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
/* 84 */ "RealAffinity" OpHelp(""),
/* 85 */ "Cast" OpHelp("affinity(r[P1])"),
/* 86 */ "Permutation" OpHelp(""),
/* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
/* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
/* 89 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
/* 90 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
/* 91 */ "Column" OpHelp("r[P3]=PX"),
/* 92 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
/* 93 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
/* 94 */ "Count" OpHelp("r[P2]=count()"),
/* 95 */ "ReadCookie" OpHelp(""),
/* 96 */ "SetCookie" OpHelp(""),
/* 97 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
/* 98 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
/* 99 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
/* 100 */ "OpenDup" OpHelp(""),
/* 101 */ "OpenAutoindex" OpHelp("nColumn=P2"),
/* 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 */ "OpenEphemeral" OpHelp("nColumn=P2"),
/* 113 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
/* 114 */ "SorterOpen" OpHelp(""),
/* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
/* 116 */ "String8" OpHelp("r[P2]='P4'"),
/* 117 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
/* 118 */ "Close" OpHelp(""),
/* 119 */ "ColumnsUsed" OpHelp(""),
/* 120 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
/* 121 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
/* 122 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
/* 123 */ "NewRowid" OpHelp("r[P2]=rowid"),
/* 124 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
/* 125 */ "RowCell" OpHelp(""),
/* 126 */ "Delete" OpHelp(""),
/* 127 */ "ResetCount" OpHelp(""),
/* 128 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
/* 129 */ "SorterData" OpHelp("r[P2]=data"),
/* 130 */ "RowData" OpHelp("r[P2]=data"),
/* 131 */ "Rowid" OpHelp("r[P2]=rowid"),
/* 132 */ "NullRow" OpHelp(""),
/* 133 */ "SeekEnd" OpHelp(""),
/* 134 */ "IdxInsert" OpHelp("key=r[P2]"),
/* 135 */ "SorterInsert" OpHelp("key=r[P2]"),
/* 136 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
/* 137 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
/* 138 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 139 */ "FinishSeek" OpHelp(""),
/* 140 */ "Destroy" OpHelp(""),
/* 141 */ "Clear" OpHelp(""),
/* 142 */ "ResetSorter" OpHelp(""),
/* 143 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
/* 144 */ "SqlExec" OpHelp(""),
/* 145 */ "ParseSchema" OpHelp(""),
/* 146 */ "LoadAnalysis" OpHelp(""),
/* 147 */ "DropTable" OpHelp(""),
/* 148 */ "DropIndex" OpHelp(""),
/* 149 */ "DropTrigger" OpHelp(""),
/* 150 */ "IntegrityCk" OpHelp(""),
/* 151 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
/* 152 */ "Real" OpHelp("r[P2]=P4"),
/* 153 */ "Param" OpHelp(""),
/* 154 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
/* 155 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
/* 156 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
/* 157 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
/* 158 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 159 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
/* 160 */ "AggValue" OpHelp("r[P3]=value N=P2"),
/* 161 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
/* 162 */ "Expire" OpHelp(""),
/* 163 */ "CursorLock" OpHelp(""),
/* 164 */ "CursorUnlock" OpHelp(""),
/* 165 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
/* 166 */ "VBegin" OpHelp(""),
/* 167 */ "VCreate" OpHelp(""),
/* 168 */ "VDestroy" OpHelp(""),
/* 169 */ "VOpen" OpHelp(""),
/* 170 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
/* 171 */ "VRename" OpHelp(""),
/* 172 */ "Pagecount" OpHelp(""),
/* 173 */ "MaxPgcnt" OpHelp(""),
/* 174 */ "Trace" OpHelp(""),
/* 175 */ "CursorHint" OpHelp(""),
/* 176 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
/* 177 */ "Noop" OpHelp(""),
/* 178 */ "Explain" OpHelp(""),
/* 179 */ "Abortable" OpHelp(""),
};
return azName[i];
}
#endif
/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
|
| ︙ | ︙ | |||
37807 37808 37809 37810 37811 37812 37813 37814 37815 37816 37817 37818 37819 37820 |
}else{
pFile->ctrlFlags |= mask;
}
}
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
| > | 37990 37991 37992 37993 37994 37995 37996 37997 37998 37999 38000 38001 38002 38003 38004 |
}else{
pFile->ctrlFlags |= mask;
}
}
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
static int unixFcntlExternalReader(unixFile*, int*);
/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
|
| ︙ | ︙ | |||
37923 37924 37925 37926 37927 37928 37929 37930 37931 37932 37933 37934 37935 37936 |
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
case SQLITE_FCNTL_SET_LOCKPROXYFILE:
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
}
return SQLITE_NOTFOUND;
}
/*
** If pFd->sectorSize is non-zero when this function is called, it is a
** no-op. Otherwise, the values of pFd->sectorSize and
| > > > > | 38107 38108 38109 38110 38111 38112 38113 38114 38115 38116 38117 38118 38119 38120 38121 38122 38123 38124 |
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
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
** no-op. Otherwise, the values of pFd->sectorSize and
|
| ︙ | ︙ | |||
38167 38168 38169 38170 38171 38172 38173 38174 38175 38176 38177 38178 38179 38180 | }; /* ** Constants used for locking */ #define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ #define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ /* ** Apply posix advisory locks for all bytes from ofst through ofst+n-1. ** ** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking ** otherwise. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 38355 38356 38357 38358 38359 38360 38361 38362 38363 38364 38365 38366 38367 38368 38369 38370 38371 38372 38373 38374 38375 38376 38377 38378 38379 38380 38381 38382 38383 38384 38385 38386 38387 38388 38389 38390 38391 38392 38393 38394 38395 38396 38397 38398 38399 38400 38401 38402 |
};
/*
** Constants used for locking
*/
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
/*
** Use F_GETLK to check whether or not there are any readers with open
** wal-mode transactions in other processes on database file pFile. If
** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
** such transactions, or 0 otherwise. If an error occurs, return an
** SQLite error code. The final value of *piOut is undefined in this
** case.
*/
static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
int rc = SQLITE_OK;
*piOut = 0;
if( pFile->pShm){
unixShmNode *pShmNode = pFile->pShm->pShmNode;
struct flock f;
memset(&f, 0, sizeof(f));
f.l_type = F_WRLCK;
f.l_whence = SEEK_SET;
f.l_start = UNIX_SHM_BASE + 3;
f.l_len = SQLITE_SHM_NLOCK - 3;
sqlite3_mutex_enter(pShmNode->pShmMutex);
if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
rc = SQLITE_IOERR_LOCK;
}else{
*piOut = (f.l_type!=F_UNLCK);
}
sqlite3_mutex_leave(pShmNode->pShmMutex);
}
return rc;
}
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
** otherwise.
*/
|
| ︙ | ︙ | |||
41884 41885 41886 41887 41888 41889 41890 41891 41892 41893 41894 41895 41896 41897 |
assert( ArraySize(aSyscall)==29 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
return SQLITE_OK;
}
/*
** Shutdown the operating system interface.
**
** Some operating systems might need to do some cleanup in this routine,
| > > > > > > > > > > > > > > > > | 42106 42107 42108 42109 42110 42111 42112 42113 42114 42115 42116 42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 42128 42129 42130 42131 42132 42133 42134 42135 |
assert( ArraySize(aSyscall)==29 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
/* Validate lock assumptions */
assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
/* Locks:
** WRITE UNIX_SHM_BASE 120
** CKPT UNIX_SHM_BASE+1 121
** RECOVER UNIX_SHM_BASE+2 122
** READ-0 UNIX_SHM_BASE+3 123
** READ-1 UNIX_SHM_BASE+4 124
** 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 */
return SQLITE_OK;
}
/*
** Shutdown the operating system interface.
**
** Some operating systems might need to do some cleanup in this routine,
|
| ︙ | ︙ | |||
48277 48278 48279 48280 48281 48282 48283 | ** This file implements an in-memory VFS. A database is held as a contiguous ** block of memory. ** ** This file also implements interface sqlite3_serialize() and ** sqlite3_deserialize(). */ /* #include "sqliteInt.h" */ | | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > > > > > > > > > > > > > > > > > > | 48515 48516 48517 48518 48519 48520 48521 48522 48523 48524 48525 48526 48527 48528 48529 48530 48531 48532 48533 48534 48535 48536 48537 48538 48539 48540 48541 48542 48543 48544 48545 48546 48547 48548 48549 48550 48551 48552 48553 48554 48555 48556 48557 48558 48559 48560 48561 48562 48563 48564 48565 48566 48567 48568 48569 48570 48571 48572 48573 48574 48575 48576 48577 48578 48579 48580 48581 48582 48583 48584 48585 48586 48587 48588 48589 48590 48591 48592 48593 48594 48595 48596 48597 48598 48599 48600 48601 48602 48603 48604 48605 48606 48607 48608 48609 48610 |
** This file implements an in-memory VFS. A database is held as a contiguous
** block of memory.
**
** This file also implements interface sqlite3_serialize() and
** sqlite3_deserialize().
*/
/* #include "sqliteInt.h" */
#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
/* Storage for a memdb file.
**
** An memdb object can be shared or separate. Shared memdb objects can be
** used by more than one database connection. Mutexes are used by shared
** memdb objects to coordinate access. Separate memdb objects are only
** connected to a single database connection and do not require additional
** mutexes.
**
** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
** using "file:/name?vfs=memdb". The first character of the name must be
** "/" or else the object will be a separate memdb object. All shared
** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
**
** Separate memdb objects are created using a name that does not begin
** with "/" or using sqlite3_deserialize().
**
** Access rules for shared MemStore objects:
**
** * .zFName is initialized when the object is created and afterwards
** is unchanged until the object is destroyed. So it can be accessed
** at any time as long as we know the object is not being destroyed,
** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
** .pMutex is held or the object is not part of memdb_g.apMemStore[].
**
** * Can .pMutex can only be changed while holding the
** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
** of memdb_g.apMemStore[].
**
** * Other fields can only be changed while holding the .pMutex mutex
** or when the .nRef is less than zero and the object is not part of
** memdb_g.apMemStore[].
**
** * The .aData pointer has the added requirement that it can can only
** be changed (for resizing) when nMmap is zero.
**
*/
struct MemStore {
sqlite3_int64 sz; /* Size of the file */
sqlite3_int64 szAlloc; /* Space allocated to aData */
sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
sqlite3_mutex *pMutex; /* Used by shared stores only */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
int nRdLock; /* Number of readers */
int nWrLock; /* Number of writers. (Always 0 or 1) */
int nRef; /* Number of users of this MemStore */
char *zFName; /* The filename for shared stores */
};
/* An open file */
struct MemFile {
sqlite3_file base; /* IO methods */
MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
/*
** File-scope variables for holding the memdb files that are accessible
** to multiple database connections in separate threads.
**
** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
*/
static struct MemFS {
int nMemStore; /* Number of shared MemStore objects */
MemStore **apMemStore; /* Array of all shared MemStore objects */
} memdb_g;
/*
** Methods for MemFile
*/
static int memdbClose(sqlite3_file*);
static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
|
| ︙ | ︙ | |||
48355 48356 48357 48358 48359 48360 48361 | memdbDlError, /* xDlError */ memdbDlSym, /* xDlSym */ memdbDlClose, /* xDlClose */ memdbRandomness, /* xRandomness */ memdbSleep, /* xSleep */ 0, /* memdbCurrentTime, */ /* xCurrentTime */ memdbGetLastError, /* xGetLastError */ | | > > > | 48650 48651 48652 48653 48654 48655 48656 48657 48658 48659 48660 48661 48662 48663 48664 48665 48666 48667 |
memdbDlError, /* xDlError */
memdbDlSym, /* xDlSym */
memdbDlClose, /* xDlClose */
memdbRandomness, /* xRandomness */
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
0, /* xSetSystemCall */
0, /* xGetSystemCall */
0, /* xNextSystemCall */
};
static const sqlite3_io_methods memdb_io_methods = {
3, /* iVersion */
memdbClose, /* xClose */
memdbRead, /* xRead */
memdbWrite, /* xWrite */
|
| ︙ | ︙ | |||
48380 48381 48382 48383 48384 48385 48386 48387 48388 48389 48390 | 0, /* xShmLock */ 0, /* xShmBarrier */ 0, /* xShmUnmap */ memdbFetch, /* xFetch */ memdbUnfetch /* xUnfetch */ }; /* ** Close an memdb-file. | > > > > > > > > > > > > > > > > > > > > | < < < | > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > | > > > | | | > | > > > > > > > | > > | > > | > > | > > | > > | > > > > | | < | > > > > > | > > > > > > > > > > > > > > > > > > > | > | | > | > | > > > | > > | > > > > | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | > > > | | | 48678 48679 48680 48681 48682 48683 48684 48685 48686 48687 48688 48689 48690 48691 48692 48693 48694 48695 48696 48697 48698 48699 48700 48701 48702 48703 48704 48705 48706 48707 48708 48709 48710 48711 48712 48713 48714 48715 48716 48717 48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 48733 48734 48735 48736 48737 48738 48739 48740 48741 48742 48743 48744 48745 48746 48747 48748 48749 48750 48751 48752 48753 48754 48755 48756 48757 48758 48759 48760 48761 48762 48763 48764 48765 48766 48767 48768 48769 48770 48771 48772 48773 48774 48775 48776 48777 48778 48779 48780 48781 48782 48783 48784 48785 48786 48787 48788 48789 48790 48791 48792 48793 48794 48795 48796 48797 48798 48799 48800 48801 48802 48803 48804 48805 48806 48807 48808 48809 48810 48811 48812 48813 48814 48815 48816 48817 48818 48819 48820 48821 48822 48823 48824 48825 48826 48827 48828 48829 48830 48831 48832 48833 48834 48835 48836 48837 48838 48839 48840 48841 48842 48843 48844 48845 48846 48847 48848 48849 48850 48851 48852 48853 48854 48855 48856 48857 48858 48859 48860 48861 48862 48863 48864 48865 48866 48867 48868 48869 48870 48871 48872 48873 48874 48875 48876 48877 48878 48879 48880 48881 48882 48883 48884 48885 48886 48887 48888 48889 48890 48891 48892 48893 48894 48895 48896 48897 48898 48899 48900 48901 48902 48903 48904 48905 48906 48907 48908 48909 48910 48911 48912 48913 48914 48915 48916 48917 48918 48919 48920 48921 48922 48923 48924 48925 48926 48927 48928 48929 48930 48931 48932 48933 48934 48935 48936 48937 48938 48939 48940 48941 48942 48943 48944 48945 48946 48947 48948 48949 48950 48951 48952 48953 48954 48955 48956 48957 48958 48959 48960 48961 48962 48963 48964 48965 48966 48967 48968 48969 48970 48971 48972 48973 48974 48975 48976 48977 48978 48979 48980 48981 48982 48983 48984 48985 48986 48987 48988 48989 48990 48991 48992 48993 48994 48995 48996 48997 48998 48999 49000 49001 49002 49003 49004 49005 49006 49007 49008 49009 49010 49011 49012 49013 49014 49015 49016 49017 49018 49019 49020 49021 49022 49023 49024 49025 49026 49027 49028 49029 49030 49031 49032 49033 49034 49035 49036 49037 49038 49039 49040 49041 49042 49043 49044 49045 49046 49047 49048 49049 49050 49051 49052 49053 49054 49055 49056 49057 49058 49059 49060 49061 49062 49063 49064 49065 49066 49067 49068 49069 49070 49071 49072 49073 49074 49075 49076 49077 49078 49079 49080 49081 49082 |
0, /* xShmLock */
0, /* xShmBarrier */
0, /* xShmUnmap */
memdbFetch, /* xFetch */
memdbUnfetch /* xUnfetch */
};
/*
** Enter/leave the mutex on a MemStore
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
static void memdbEnter(MemStore *p){
UNUSED_PARAMETER(p);
}
static void memdbLeave(MemStore *p){
UNUSED_PARAMETER(p);
}
#else
static void memdbEnter(MemStore *p){
sqlite3_mutex_enter(p->pMutex);
}
static void memdbLeave(MemStore *p){
sqlite3_mutex_leave(p->pMutex);
}
#endif
/*
** Close an memdb-file.
** Free the underlying MemStore object when its refcount drops to zero
** or less.
*/
static int memdbClose(sqlite3_file *pFile){
MemStore *p = ((MemFile*)pFile)->pStore;
if( p->zFName ){
int i;
#ifndef SQLITE_MUTEX_OMIT
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
sqlite3_mutex_enter(pVfsMutex);
for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
if( memdb_g.apMemStore[i]==p ){
memdbEnter(p);
if( p->nRef==1 ){
memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
if( memdb_g.nMemStore==0 ){
sqlite3_free(memdb_g.apMemStore);
memdb_g.apMemStore = 0;
}
}
break;
}
}
sqlite3_mutex_leave(pVfsMutex);
}else{
memdbEnter(p);
}
p->nRef--;
if( p->nRef<=0 ){
if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
sqlite3_free(p->aData);
}
memdbLeave(p);
sqlite3_mutex_free(p->pMutex);
sqlite3_free(p);
}else{
memdbLeave(p);
}
return SQLITE_OK;
}
/*
** Read data from an memdb-file.
*/
static int memdbRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
memdbLeave(p);
return SQLITE_OK;
}
/*
** 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 || p->nMmap>0 ){
return SQLITE_FULL;
}
if( newSz>p->szMax ){
return SQLITE_FULL;
}
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlite3Realloc(p->aData, newSz);
if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
p->szAlloc = newSz;
return SQLITE_OK;
}
/*
** Write data to an memdb-file.
*/
static int memdbWrite(
sqlite3_file *pFile,
const void *z,
int iAmt,
sqlite_int64 iOfst
){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
/* Can't happen: memdbLock() will return SQLITE_READONLY before
** reaching this point */
memdbLeave(p);
return SQLITE_IOERR_WRITE;
}
if( iOfst+iAmt>p->sz ){
int rc;
if( iOfst+iAmt>p->szAlloc
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
memdbLeave(p);
return SQLITE_OK;
}
/*
** Truncate an memdb-file.
**
** In rollback mode (which is always the case for memdb, as it does not
** 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( NEVER(size>p->sz) ){
rc = SQLITE_FULL;
}else{
p->sz = size;
}
memdbLeave(p);
return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
UNUSED_PARAMETER(pFile);
UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
/*
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
*pSize = p->sz;
memdbLeave(p);
return SQLITE_OK;
}
/*
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
MemFile *pThis = (MemFile*)pFile;
MemStore *p = pThis->pStore;
int rc = SQLITE_OK;
if( eLock==pThis->eLock ) return SQLITE_OK;
memdbEnter(p);
if( eLock>SQLITE_LOCK_SHARED ){
if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
rc = SQLITE_READONLY;
}else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
if( p->nWrLock ){
rc = SQLITE_BUSY;
}else{
p->nWrLock = 1;
}
}
}else if( eLock==SQLITE_LOCK_SHARED ){
if( pThis->eLock > SQLITE_LOCK_SHARED ){
assert( p->nWrLock==1 );
p->nWrLock = 0;
}else if( p->nWrLock ){
rc = SQLITE_BUSY;
}else{
p->nRdLock++;
}
}else{
assert( eLock==SQLITE_LOCK_NONE );
if( pThis->eLock>SQLITE_LOCK_SHARED ){
assert( p->nWrLock==1 );
p->nWrLock = 0;
}
assert( p->nRdLock>0 );
p->nRdLock--;
}
if( rc==SQLITE_OK ) pThis->eLock = eLock;
memdbLeave(p);
return rc;
}
#if 0
/*
** This interface is only used for crash recovery, which does not
** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
return SQLITE_OK;
}
#endif
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
}
if( op==SQLITE_FCNTL_SIZE_LIMIT ){
sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
if( iLimit<p->sz ){
if( iLimit<0 ){
iLimit = p->szMax;
}else{
iLimit = p->sz;
}
}
p->szMax = iLimit;
*(sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
memdbLeave(p);
return rc;
}
#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
/*
** Return the sector-size in bytes for an memdb-file.
*/
static int memdbSectorSize(sqlite3_file *pFile){
return 1024;
}
#endif
/*
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
UNUSED_PARAMETER(pFile);
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
SQLITE_IOCAP_SEQUENTIAL;
}
/* Fetch a page of a memory-mapped file */
static int memdbFetch(
sqlite3_file *pFile,
sqlite3_int64 iOfst,
int iAmt,
void **pp
){
MemStore *p = ((MemFile*)pFile)->pStore;
memdbEnter(p);
if( iOfst+iAmt>p->sz ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
MemStore *p = ((MemFile*)pFile)->pStore;
UNUSED_PARAMETER(iOfst);
UNUSED_PARAMETER(pPage);
memdbEnter(p);
p->nMmap--;
memdbLeave(p);
return SQLITE_OK;
}
/*
** Open an mem file handle.
*/
static int memdbOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFd,
int flags,
int *pOutFlags
){
MemFile *pFile = (MemFile*)pFd;
MemStore *p = 0;
int szName;
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
}
memset(pFile, 0, sizeof(*p));
szName = sqlite3Strlen30(zName);
if( szName>1 && zName[0]=='/' ){
int i;
#ifndef SQLITE_MUTEX_OMIT
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
sqlite3_mutex_enter(pVfsMutex);
for(i=0; i<memdb_g.nMemStore; i++){
if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
p = memdb_g.apMemStore[i];
break;
}
}
if( p==0 ){
MemStore **apNew;
p = sqlite3Malloc( sizeof(*p) + szName + 3 );
if( p==0 ){
sqlite3_mutex_leave(pVfsMutex);
return SQLITE_NOMEM;
}
apNew = sqlite3Realloc(memdb_g.apMemStore,
sizeof(apNew[0])*(memdb_g.nMemStore+1) );
if( apNew==0 ){
sqlite3_free(p);
sqlite3_mutex_leave(pVfsMutex);
return SQLITE_NOMEM;
}
apNew[memdb_g.nMemStore++] = p;
memdb_g.apMemStore = apNew;
memset(p, 0, sizeof(*p));
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
p->zFName = (char*)&p[1];
memcpy(p->zFName, zName, szName+1);
p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( p->pMutex==0 ){
memdb_g.nMemStore--;
sqlite3_free(p);
sqlite3_mutex_leave(pVfsMutex);
return SQLITE_NOMEM;
}
p->nRef = 1;
memdbEnter(p);
}else{
memdbEnter(p);
p->nRef++;
}
sqlite3_mutex_leave(pVfsMutex);
}else{
p = sqlite3Malloc( sizeof(*p) );
if( p==0 ){
return SQLITE_NOMEM;
}
memset(p, 0, sizeof(*p));
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
}
pFile->pStore = p;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*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 */
/*
** Delete the file located at zPath. If the dirSync argument is true,
|
| ︙ | ︙ | |||
48631 48632 48633 48634 48635 48636 48637 48638 48639 48640 48641 48642 48643 48644 48645 48646 48647 48648 48649 48650 48651 48652 48653 48654 48655 48656 48657 48658 48659 |
*/
static int memdbAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
*pResOut = 0;
return SQLITE_OK;
}
/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int memdbFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
/*
** Open the dynamic library located at zPath and return a handle.
*/
| > > > > | 49096 49097 49098 49099 49100 49101 49102 49103 49104 49105 49106 49107 49108 49109 49110 49111 49112 49113 49114 49115 49116 49117 49118 49119 49120 49121 49122 49123 49124 49125 49126 49127 49128 |
*/
static int memdbAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
UNUSED_PARAMETER(pVfs);
UNUSED_PARAMETER(zPath);
UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int memdbFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
UNUSED_PARAMETER(pVfs);
sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
/*
** Open the dynamic library located at zPath and return a handle.
*/
|
| ︙ | ︙ | |||
48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 48733 48734 |
/*
** Translate a database connection pointer and schema name into a
** MemFile pointer.
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
return p;
}
/*
** Return the serialization of a database
*/
SQLITE_API unsigned char *sqlite3_serialize(
| > > > > > | 49187 49188 49189 49190 49191 49192 49193 49194 49195 49196 49197 49198 49199 49200 49201 49202 49203 49204 49205 49206 49207 49208 |
/*
** Translate a database connection pointer and schema name into a
** MemFile pointer.
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
MemFile *p = 0;
MemStore *pStore;
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
pStore = p->pStore;
memdbEnter(pStore);
if( pStore->zFName!=0 ) p = 0;
memdbLeave(pStore);
return p;
}
/*
** Return the serialization of a database
*/
SQLITE_API unsigned char *sqlite3_serialize(
|
| ︙ | ︙ | |||
48756 48757 48758 48759 48760 48761 48762 |
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
p = memdbFromDbSchema(db, zSchema);
iDb = sqlite3FindDbName(db, zSchema);
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
| > > | | | | | 49230 49231 49232 49233 49234 49235 49236 49237 49238 49239 49240 49241 49242 49243 49244 49245 49246 49247 49248 49249 49250 49251 |
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
p = memdbFromDbSchema(db, zSchema);
iDb = sqlite3FindDbName(db, zSchema);
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
MemStore *pStore = p->pStore;
assert( pStore->pMutex==0 );
if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
pOut = pStore->aData;
}else{
pOut = sqlite3_malloc64( pStore->sz );
if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
pBt = db->aDb[iDb].pBt;
if( pBt==0 ) return 0;
szPage = sqlite3BtreeGetPageSize(pBt);
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
|
| ︙ | ︙ | |||
48855 48856 48857 48858 48859 48860 48861 |
rc = SQLITE_ERROR;
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
if( p==0 ){
rc = SQLITE_ERROR;
}else{
| > | | | | | | | | | | 49331 49332 49333 49334 49335 49336 49337 49338 49339 49340 49341 49342 49343 49344 49345 49346 49347 49348 49349 49350 49351 49352 49353 49354 49355 49356 49357 49358 49359 49360 49361 49362 49363 49364 49365 49366 49367 49368 49369 49370 49371 49372 49373 49374 49375 49376 49377 49378 49379 49380 49381 49382 49383 |
rc = SQLITE_ERROR;
goto end_deserialize;
}
p = memdbFromDbSchema(db, zSchema);
if( p==0 ){
rc = SQLITE_ERROR;
}else{
MemStore *pStore = p->pStore;
pStore->aData = pData;
pData = 0;
pStore->sz = szDb;
pStore->szAlloc = szBuf;
pStore->szMax = szBuf;
if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
}
pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
end_deserialize:
sqlite3_finalize(pStmt);
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
sqlite3_free(pData);
}
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
SQLITE_PRIVATE int sqlite3MemdbInit(void){
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
unsigned int sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
** it in, to be safe, but it is marked as NO_TEST since there
** is no way to reach it under most builds. */
if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
memdb_vfs.szOsFile = sz;
return sqlite3_vfs_register(&memdb_vfs, 0);
}
#endif /* SQLITE_OMIT_DESERIALIZE */
/************** End of memdb.c ***********************************************/
/************** Begin file bitvec.c ******************************************/
/*
** 2008 February 16
**
** The author disclaims copyright to this source code. In place of
|
| ︙ | ︙ | |||
56078 56079 56080 56081 56082 56083 56084 |
**
** This function is only called right before committing a transaction.
** Once this function has been called, the transaction must either be
** rolled back or committed. It is not safe to call this function and
** then continue writing to the database.
*/
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
| | > | 56555 56556 56557 56558 56559 56560 56561 56562 56563 56564 56565 56566 56567 56568 56569 56570 |
**
** This function is only called right before committing a transaction.
** Once this function has been called, the transaction must either be
** rolled back or committed. It is not safe to call this function and
** then continue writing to the database.
*/
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
assert( pPager->dbSize>=nPage || CORRUPT_DB );
testcase( pPager->dbSize<nPage );
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
/* At one point the code here called assertTruncateConstraint() to
** ensure that all pages being truncated away by this operation are,
** if one or more savepoints are open, present in the savepoint
** journal so that they can be restored if the savepoint is rolled
|
| ︙ | ︙ | |||
56806 56807 56808 56809 56810 56811 56812 |
void (*xReinit)(DbPage*) /* Function to reinitialize pages */
){
u8 *pPtr;
Pager *pPager = 0; /* Pager object to allocate and return */
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
| | | 57284 57285 57286 57287 57288 57289 57290 57291 57292 57293 57294 57295 57296 57297 57298 |
void (*xReinit)(DbPage*) /* Function to reinitialize pages */
){
u8 *pPtr;
Pager *pPager = 0; /* Pager object to allocate and return */
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
#endif
int readOnly = 0; /* True if this is a read-only file */
int journalFileSize; /* Bytes to allocate for each journal fd */
char *zPathname = 0; /* Full path to database file */
|
| ︙ | ︙ | |||
57010 57011 57012 57013 57014 57015 57016 |
/* 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 );
| | | 57488 57489 57490 57491 57492 57493 57494 57495 57496 57497 57498 57499 57500 57501 57502 |
/* 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
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:
|
| ︙ | ︙ | |||
57978 57979 57980 57981 57982 57983 57984 |
SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
int rc = SQLITE_OK;
if( pPager->errCode ) return pPager->errCode;
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
pPager->subjInMemory = (u8)subjInMemory;
| | | 58456 58457 58458 58459 58460 58461 58462 58463 58464 58465 58466 58467 58468 58469 58470 |
SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
int rc = SQLITE_OK;
if( pPager->errCode ) return pPager->errCode;
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
pPager->subjInMemory = (u8)subjInMemory;
if( pPager->eState==PAGER_READER ){
assert( pPager->pInJournal==0 );
if( pagerUseWal(pPager) ){
/* If the pager is configured to use locking_mode=exclusive, and an
** exclusive lock on the database is not already held, obtain it now.
*/
if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
|
| ︙ | ︙ | |||
60852 60853 60854 60855 60856 60857 60858 |
** actually needed.
*/
static void walCleanupHash(Wal *pWal){
WalHashLoc sLoc; /* Hash table location */
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
| < | | | 61330 61331 61332 61333 61334 61335 61336 61337 61338 61339 61340 61341 61342 61343 61344 61345 61346 61347 61348 61349 61350 61351 61352 61353 61354 61355 61356 61357 61358 61359 |
** actually needed.
*/
static void walCleanupHash(Wal *pWal){
WalHashLoc sLoc; /* Hash table location */
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
assert( pWal->writeLock );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );
if( pWal->hdr.mxFrame==0 ) return;
/* Obtain pointers to the hash-table and page-number array containing
** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
** that the page said hash-table and array reside on is already mapped.(1)
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
*/
iLimit = pWal->hdr.mxFrame - sLoc.iZero;
assert( iLimit>0 );
for(i=0; i<HASHTABLE_NSLOT; i++){
|
| ︙ | ︙ | |||
65498 65499 65500 65501 65502 65503 65504 |
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
| | | 65975 65976 65977 65978 65979 65980 65981 65982 65983 65984 65985 65986 65987 65988 65989 |
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
assert( pBtree->hasIncrblobCur );
assert( sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 ){
pBtree->hasIncrblobCur = 1;
if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
|
| ︙ | ︙ | |||
66399 66400 66401 66402 66403 66404 66405 66406 66407 66408 66409 66410 66411 66412 | int cbrk; /* Offset to the cell content area */ int nCell; /* Number of cells on the page */ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ unsigned char *src; /* Source of content */ int iCellFirst; /* First allowable cell index */ int iCellLast; /* Last possible cell index */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); temp = 0; | > | 66876 66877 66878 66879 66880 66881 66882 66883 66884 66885 66886 66887 66888 66889 66890 | int cbrk; /* Offset to the cell content area */ int nCell; /* Number of cells on the page */ unsigned char *data; /* The page data */ unsigned char *temp; /* Temp area for cell content */ unsigned char *src; /* Source of content */ int iCellFirst; /* First allowable cell index */ int iCellLast; /* Last possible cell index */ int iCellStart; /* First cell offset in input */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); temp = 0; |
| ︙ | ︙ | |||
66440 66441 66442 66443 66444 66445 66446 |
}
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;
| | > | | | | < < | | 66918 66919 66920 66921 66922 66923 66924 66925 66926 66927 66928 66929 66930 66931 66932 66933 66934 66935 66936 66937 66938 66939 66940 66941 66942 66943 66944 66945 66946 66947 66948 66949 66950 66951 66952 66953 66954 66955 66956 66957 66958 66959 66960 66961 66962 66963 66964 66965 66966 66967 66968 66969 66970 66971 66972 66973 66974 66975 66976 66977 |
}
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( 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){
pc = get2byte(pAddr);
if( pc<iFree ){ put2byte(pAddr, pc+sz); }
else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
}
goto defragment_out;
}
}
}
cbrk = usableSize;
iCellLast = usableSize - 4;
iCellStart = get2byte(&data[hdr+5]);
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
testcase( pc==iCellFirst );
testcase( pc==iCellLast );
/* These conditions have already been verified in btreeInitPage()
** if PRAGMA cell_size_check=ON.
*/
if( pc<iCellStart || pc>iCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrk<iCellStart || pc+size>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
if( cbrk==pc ) continue;
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
memcpy(&temp[iCellStart], &data[iCellStart], (cbrk+size) - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
}
data[hdr+7] = 0;
defragment_out:
|
| ︙ | ︙ | |||
70345 70346 70347 70348 70349 70350 70351 |
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
| | > > | 70822 70823 70824 70825 70826 70827 70828 70829 70830 70831 70832 70833 70834 70835 70836 70837 70838 |
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
testcase( pCur->ix!=pCur->pPage->nCell-1 );
/* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
*pRes = 0;
return SQLITE_OK;
}
rc = moveToRoot(pCur);
|
| ︙ | ︙ | |||
71112 71113 71114 71115 71116 71117 71118 |
}
}else{
closest = 0;
}
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
| | | 71591 71592 71593 71594 71595 71596 71597 71598 71599 71600 71601 71602 71603 71604 71605 |
}
}else{
closest = 0;
}
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
if( iPage>mxPage || iPage<2 ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iPage==mxPage );
if( !searchList
|| (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
){
|
| ︙ | ︙ | |||
71368 71369 71370 71371 71372 71373 71374 |
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
| | < | < | < < | 71847 71848 71849 71850 71851 71852 71853 71854 71855 71856 71857 71858 71859 71860 71861 71862 71863 71864 71865 71866 71867 71868 71869 71870 71871 71872 71873 71874 71875 |
static void freePage(MemPage *pPage, int *pRC){
if( (*pRC)==SQLITE_OK ){
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
}
}
/*
** Free the overflow pages associated with the given Cell.
*/
static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
){
BtShared *pBt;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
/* Cell extends past end of page */
return SQLITE_CORRUPT_PAGE(pPage);
}
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
|
| ︙ | ︙ | |||
71441 71442 71443 71444 71445 71446 71447 71448 71449 71450 71451 71452 71453 71454 |
sqlite3PagerUnref(pOvfl->pDbPage);
}
if( rc ) return rc;
ovflPgno = iNext;
}
return SQLITE_OK;
}
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
** allocated and filled in as necessary. The calling procedure
** is responsible for making sure sufficient space has been allocated
** for pCell[].
| > > > > > > > > > > > > > > > | 71916 71917 71918 71919 71920 71921 71922 71923 71924 71925 71926 71927 71928 71929 71930 71931 71932 71933 71934 71935 71936 71937 71938 71939 71940 71941 71942 71943 71944 |
sqlite3PagerUnref(pOvfl->pDbPage);
}
if( rc ) return rc;
ovflPgno = iNext;
}
return SQLITE_OK;
}
/* Call xParseCell to compute the size of a cell. If the cell contains
** overflow, then invoke cellClearOverflow to clear out that overflow.
** STore the result code (SQLITE_OK or some error code) in rc.
**
** Implemented as macro to force inlining for performance.
*/
#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
pPage->xParseCell(pPage, pCell, &sInfo); \
if( sInfo.nLocal!=sInfo.nPayload ){ \
rc = clearCellOverflow(pPage, pCell, &sInfo); \
}else{ \
rc = SQLITE_OK; \
}
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
** allocated and filled in as necessary. The calling procedure
** is responsible for making sure sufficient space has been allocated
** for pCell[].
|
| ︙ | ︙ | |||
71964 71965 71966 71967 71968 71969 71970 |
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
while( 1/*exit by break*/ ){
u8 *pCell = pCArray->apCell[i];
u16 sz = pCArray->szCell[i];
assert( sz>0 );
| | | < | 72454 72455 72456 72457 72458 72459 72460 72461 72462 72463 72464 72465 72466 72467 72468 72469 72470 72471 72472 72473 72474 72475 72476 72477 72478 72479 72480 72481 72482 |
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
while( 1/*exit by break*/ ){
u8 *pCell = pCArray->apCell[i];
u16 sz = pCArray->szCell[i];
assert( sz>0 );
if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
}else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
&& (uptr)(pCell)<(uptr)pSrcEnd
){
return SQLITE_CORRUPT_BKPT;
}
pData -= sz;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
memmove(pData, pCell, sz);
assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
i++;
if( i>=iEnd ) break;
if( pCArray->ixNx[k]<=i ){
k++;
pSrcEnd = pCArray->apEnd[k];
}
}
|
| ︙ | ︙ | |||
72118 72119 72120 72121 72122 72123 72124 |
if( pFree!=(pCell + sz) ){
if( pFree ){
assert( pFree>aData && (pFree - aData)<65536 );
freeSpace(pPg, (u16)(pFree - aData), szFree);
}
pFree = pCell;
szFree = sz;
| | > > | 72607 72608 72609 72610 72611 72612 72613 72614 72615 72616 72617 72618 72619 72620 72621 72622 72623 |
if( pFree!=(pCell + sz) ){
if( pFree ){
assert( pFree>aData && (pFree - aData)<65536 );
freeSpace(pPg, (u16)(pFree - aData), szFree);
}
pFree = pCell;
szFree = sz;
if( pFree+sz>pEnd ){
return 0;
}
}else{
pFree = pCell;
szFree += sz;
}
nRet++;
}
}
|
| ︙ | ︙ | |||
72771 72772 72773 72774 72775 72776 72777 |
assert( iSpace1 <= (int)pBt->pageSize );
memcpy(pTemp, apDiv[i], sz);
b.apCell[b.nCell] = pTemp+leafCorrection;
assert( leafCorrection==0 || leafCorrection==4 );
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
if( !pOld->leaf ){
assert( leafCorrection==0 );
| | | 73262 73263 73264 73265 73266 73267 73268 73269 73270 73271 73272 73273 73274 73275 73276 |
assert( iSpace1 <= (int)pBt->pageSize );
memcpy(pTemp, apDiv[i], sz);
b.apCell[b.nCell] = pTemp+leafCorrection;
assert( leafCorrection==0 || leafCorrection==4 );
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
if( !pOld->leaf ){
assert( leafCorrection==0 );
assert( pOld->hdrOffset==0 || CORRUPT_DB );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
}else{
assert( leafCorrection==4 );
while( b.szCell[b.nCell]<4 ){
/* Do not allow any cells smaller than 4 bytes. If a smaller cell
|
| ︙ | ︙ | |||
73094 73095 73096 73097 73098 73099 73100 73101 73102 73103 73104 73105 73106 73107 |
}
/* Insert new divider cells into pParent. */
for(i=0; i<nNew-1; i++){
u8 *pCell;
u8 *pTemp;
int sz;
MemPage *pNew = apNew[i];
j = cntNew[i];
assert( j<nMaxCells );
assert( b.apCell[j]!=0 );
pCell = b.apCell[j];
sz = b.szCell[j] + leafCorrection;
| > | 73585 73586 73587 73588 73589 73590 73591 73592 73593 73594 73595 73596 73597 73598 73599 |
}
/* Insert new divider cells into pParent. */
for(i=0; i<nNew-1; i++){
u8 *pCell;
u8 *pTemp;
int sz;
u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
assert( j<nMaxCells );
assert( b.apCell[j]!=0 );
pCell = b.apCell[j];
sz = b.szCell[j] + leafCorrection;
|
| ︙ | ︙ | |||
73137 73138 73139 73140 73141 73142 73143 73144 73145 73146 73147 73148 73149 73150 |
assert(leafCorrection==4);
sz = pParent->xCellSize(pParent, pCell);
}
}
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
}
/* Now update the actual sibling pages. The order in which they are updated
** is important, as this code needs to avoid disrupting any page from which
| > > > > > > | 73629 73630 73631 73632 73633 73634 73635 73636 73637 73638 73639 73640 73641 73642 73643 73644 73645 73646 73647 73648 |
assert(leafCorrection==4);
sz = pParent->xCellSize(pParent, pCell);
}
}
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
goto balance_cleanup;
}
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
}
/* Now update the actual sibling pages. The order in which they are updated
** is important, as this code needs to avoid disrupting any page from which
|
| ︙ | ︙ | |||
73679 73680 73681 73682 73683 73684 73685 73686 73687 73688 73689 73690 73691 |
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
** not to clear the cursor here.
*/
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
}
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
| > > > > > > > > > | > | 74177 74178 74179 74180 74181 74182 74183 74184 74185 74186 74187 74188 74189 74190 74191 74192 74193 74194 74195 74196 74197 74198 74199 74200 74201 74202 74203 74204 74205 74206 74207 |
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
** not to clear the cursor here.
*/
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
if( loc && pCur->iPage<0 ){
/* This can only happen if the schema is corrupt such that there is more
** than one table or index with the same root page as used by the cursor.
** Which can only happen if the SQLITE_NoSchemaError flag was set when
** the schema was loaded. This cannot be asserted though, as a user might
** set the flag, load the schema, and then unset the flag. */
return SQLITE_CORRUPT_BKPT;
}
}
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
if( p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
}
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
*/
#ifdef SQLITE_DEBUG
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
|
| ︙ | ︙ | |||
73766 73767 73768 73769 73770 73771 73772 |
BtreePayload x2;
x2.pData = pX->pKey;
x2.nData = pX->nKey;
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
}
| < | | 74274 74275 74276 74277 74278 74279 74280 74281 74282 74283 74284 74285 74286 74287 74288 74289 74290 74291 74292 74293 74294 74295 74296 74297 |
BtreePayload x2;
x2.pData = pX->pKey;
x2.nData = pX->nKey;
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
}
}
assert( pCur->eState==CURSOR_VALID
|| (pCur->eState==CURSOR_INVALID && loc)
|| CORRUPT_DB );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
if( NEVER(pCur->eState>CURSOR_INVALID) ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
}
if( rc ) return rc;
}
|
| ︙ | ︙ | |||
73820 73821 73822 73823 73824 73825 73826 |
if( rc ){
goto end_insert;
}
oldCell = findCell(pPage, idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
| | | 74327 74328 74329 74330 74331 74332 74333 74334 74335 74336 74337 74338 74339 74340 74341 |
if( rc ){
goto end_insert;
}
oldCell = findCell(pPage, idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
&& (!ISAUTOVACUUM || szNew<pPage->minLocal)
){
/* Overwrite the old cell with the new if they are the same size.
** We could also try to do this if the old cell is smaller, then add
|
| ︙ | ︙ | |||
74057 74058 74059 74060 74061 74062 74063 |
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
| > | | | 74564 74565 74566 74567 74568 74569 74570 74571 74572 74573 74574 74575 74576 74577 74578 74579 74580 74581 |
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
if( pCur->eState==CURSOR_REQUIRESEEK ){
rc = btreeRestoreCursorPosition(pCur);
assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
if( rc || pCur->eState!=CURSOR_VALID ) return rc;
}
assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;
|
| ︙ | ︙ | |||
74112 74113 74114 74115 74116 74117 74118 |
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
}
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
| | | | 74620 74621 74622 74623 74624 74625 74626 74627 74628 74629 74630 74631 74632 74633 74634 74635 74636 74637 74638 74639 74640 74641 74642 74643 |
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
}
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
/* Make the page containing the entry to be deleted writable. Then free any
** overflow pages associated with the entry and finally remove the cell
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
** is currently pointing to the largest entry in the sub-tree headed
** by the child-page of the cell that was just deleted from an internal
** node. The cell from the leaf node needs to be moved to the internal
|
| ︙ | ︙ | |||
74408 74409 74410 74411 74412 74413 74414 |
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;
}
| | > | < | 74916 74917 74918 74919 74920 74921 74922 74923 74924 74925 74926 74927 74928 74929 74930 74931 74932 74933 74934 74935 74936 74937 |
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;
}
BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
if( pnChange ){
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
if( freePageFlag ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
|
| ︙ | ︙ | |||
74440 74441 74442 74443 74444 74445 74446 | ** the page number of the root of the table. After this routine returns, ** the root page is empty, but still exists. ** ** This routine will fail with SQLITE_LOCKED if there are any open ** read cursors on the table. Open write cursors are moved to the ** root of the table. ** | | | < > | > | 74948 74949 74950 74951 74952 74953 74954 74955 74956 74957 74958 74959 74960 74961 74962 74963 74964 74965 74966 74967 74968 74969 74970 74971 74972 74973 74974 74975 74976 74977 74978 74979 |
** the page number of the root of the table. After this routine returns,
** the root page is empty, but still exists.
**
** This routine will fail with SQLITE_LOCKED if there are any open
** read cursors on the table. Open write cursors are moved to the
** root of the table.
**
** If pnChange is not NULL, then the integer value pointed to by pnChange
** is incremented by the number of entries in the table.
*/
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
assert( p->inTrans==TRANS_WRITE );
rc = saveAllCursors(pBt, (Pgno)iTable, 0);
if( SQLITE_OK==rc ){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
if( p->hasIncrblobCur ){
invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
}
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
return rc;
}
/*
|
| ︙ | ︙ | |||
76539 76540 76541 76542 76543 76544 76545 |
}else{
/* The MEM_Cleared bit is only allowed on NULLs */
assert( (p->flags & MEM_Cleared)==0 );
}
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
| > > | | 77048 77049 77050 77051 77052 77053 77054 77055 77056 77057 77058 77059 77060 77061 77062 77063 77064 |
}else{
/* The MEM_Cleared bit is only allowed on NULLs */
assert( (p->flags & MEM_Cleared)==0 );
}
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
|| (p->flags==MEM_Undefined
&& p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
**
** (1) Memory in Mem.zMalloc and managed by the Mem object
** (2) Memory to be freed using Mem.xDel
** (3) An ephemeral string or blob
|
| ︙ | ︙ | |||
76703 76704 76705 76706 76707 76708 76709 | /* If the bPreserve flag is set to true, then the memory cell must already ** contain a valid string or blob value. */ assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); testcase( bPreserve && pMem->z==0 ); assert( pMem->szMalloc==0 | > > | | 77214 77215 77216 77217 77218 77219 77220 77221 77222 77223 77224 77225 77226 77227 77228 77229 77230 |
/* If the bPreserve flag is set to true, then the memory cell must already
** contain a valid string or blob value. */
assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
|| (pMem->flags==MEM_Undefined
&& pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
}else{
pMem->zMalloc = sqlite3Realloc(pMem->z, n);
if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
pMem->z = pMem->zMalloc;
|
| ︙ | ︙ | |||
79859 79860 79861 79862 79863 79864 79865 |
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 ){
| < < < | < | 80372 80373 80374 80375 80376 80377 80378 80379 80380 80381 80382 80383 80384 80385 80386 |
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];
if( c=='4' ){
sqlite3_str_appendall(&x, zP4);
|
| ︙ | ︙ | |||
83565 83566 83567 83568 83569 83570 83571 | SQLITE_PRIVATE void sqlite3VdbePreUpdateHook( Vdbe *v, /* Vdbe pre-update hook is invoked by */ VdbeCursor *pCsr, /* Cursor to grab old.* values from */ int op, /* SQLITE_INSERT, UPDATE or DELETE */ const char *zDb, /* Database name */ Table *pTab, /* Modified table */ i64 iKey1, /* Initial key value */ | | > | 84074 84075 84076 84077 84078 84079 84080 84081 84082 84083 84084 84085 84086 84087 84088 84089 |
SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
Vdbe *v, /* Vdbe pre-update hook is invoked by */
VdbeCursor *pCsr, /* Cursor to grab old.* values from */
int op, /* SQLITE_INSERT, UPDATE or DELETE */
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
int iReg, /* Register for new.* record */
int iBlobWrite
){
sqlite3 *db = v->db;
i64 iKey2;
PreUpdate preupdate;
const char *zTbl = pTab->zName;
static const u8 fakeSortOrder = 0;
|
| ︙ | ︙ | |||
83601 83602 83603 83604 83605 83606 83607 83608 83609 83610 83611 83612 83613 83614 | preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nKeyField = pTab->nCol; preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked); vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked); | > | 84111 84112 84113 84114 84115 84116 84117 84118 84119 84120 84121 84122 84123 84124 84125 | preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nKeyField = pTab->nCol; preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; preupdate.iBlobWrite = iBlobWrite; db->pPreUpdate = &preupdate; db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2); db->pPreUpdate = 0; sqlite3DbFree(db, preupdate.aRecord); vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked); vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked); |
| ︙ | ︙ | |||
85526 85527 85528 85529 85530 85531 85532 85533 85534 85535 85536 85537 85538 85539 |
** or SET DEFAULT action is considered a trigger.
*/
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->v->nFrame : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
** a field of the row currently being updated or inserted.
*/
SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
| > > > > > > > > > > > | 86037 86038 86039 86040 86041 86042 86043 86044 86045 86046 86047 86048 86049 86050 86051 86052 86053 86054 86055 86056 86057 86058 86059 86060 86061 |
** or SET DEFAULT action is considered a trigger.
*/
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->v->nFrame : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is designed to be called from within a pre-update callback
** only.
*/
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->iBlobWrite : -1);
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
** a field of the row currently being updated or inserted.
*/
SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
| ︙ | ︙ | |||
86148 86149 86150 86151 86152 86153 86154 |
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
| > | > > > > > > > > > > > > > > > > > > | | | | | | | | | | < | 86670 86671 86672 86673 86674 86675 86676 86677 86678 86679 86680 86681 86682 86683 86684 86685 86686 86687 86688 86689 86690 86691 86692 86693 86694 86695 86696 86697 86698 86699 86700 86701 86702 86703 86704 86705 86706 86707 86708 86709 86710 86711 86712 86713 |
(eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
/* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
** the pMem used to hold space for the cursor has enough storage available
** in pMem->zMalloc. But for the special case of the aMem[] entries used
** to hold cursors, it is faster to in-line the logic. */
assert( pMem->flags==MEM_Undefined );
assert( (pMem->flags & MEM_Dyn)==0 );
assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
if( pMem->szMalloc<nByte ){
if( pMem->szMalloc>0 ){
sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
}
pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
if( pMem->zMalloc==0 ){
pMem->szMalloc = 0;
return 0;
}
pMem->szMalloc = nByte;
}
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->iDb = iDb;
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
pCx->uc.pCursor = (BtCursor*)
&pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
/*
** The string in pRec is known to look like an integer and to have a
** floating point value of rValue. Return true and set *piValue to the
|
| ︙ | ︙ | |||
86306 86307 86308 86309 86310 86311 86312 |
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
int rc;
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
| | > > > | 86846 86847 86848 86849 86850 86851 86852 86853 86854 86855 86856 86857 86858 86859 86860 86861 86862 86863 |
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
int rc;
sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
if( ExpandBlob(pMem) ){
pMem->u.i = 0;
return MEM_Int;
}
rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
if( rc<=0 ){
if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
pMem->u.i = ix;
return MEM_Int;
}else{
return MEM_Real;
|
| ︙ | ︙ | |||
86443 86444 86445 86446 86447 86448 86449 86450 86451 86452 86453 86454 86455 86456 |
printf("R[%d] = ", iReg);
memTracePrint(p);
if( p->pScopyFrom ){
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
#endif
#ifdef SQLITE_DEBUG
/*
** Show the values of all registers in the virtual machine. Used for
** interactive debugging.
| > > > > > | 86986 86987 86988 86989 86990 86991 86992 86993 86994 86995 86996 86997 86998 86999 87000 87001 87002 87003 87004 |
printf("R[%d] = ", iReg);
memTracePrint(p);
if( p->pScopyFrom ){
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
/**/ void sqlite3PrintMem(Mem *pMem){
memTracePrint(pMem);
printf("\n");
fflush(stdout);
}
#endif
#ifdef SQLITE_DEBUG
/*
** Show the values of all registers in the virtual machine. Used for
** interactive debugging.
|
| ︙ | ︙ | |||
87435 87436 87437 87438 87439 87440 87441 |
** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
Mem *pMem;
int i;
assert( p->nResColumn==pOp->p2 );
| | | 87983 87984 87985 87986 87987 87988 87989 87990 87991 87992 87993 87994 87995 87996 87997 |
** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
Mem *pMem;
int i;
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
/* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
/* Make sure the results of the current row are \000 terminated
** and have an assigned type. The results are de-ephemeralized as
|
| ︙ | ︙ | |||
87877 87878 87879 87880 87881 87882 87883 | } #endif /* SQLITE_OMIT_CAST */ /* Opcode: Eq P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]==r[P1] ** ** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then | | < | 88425 88426 88427 88428 88429 88430 88431 88432 88433 88434 88435 88436 88437 88438 88439 | } #endif /* SQLITE_OMIT_CAST */ /* Opcode: Eq P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]==r[P1] ** ** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then ** jump to address P2. ** ** The SQLITE_AFF_MASK portion of P5 must be an affinity character - ** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made ** to coerce both inputs according to this affinity before the ** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric ** affinity is used. Note that the affinity conversions are stored ** back into the input registers P1 and P3. So this opcode can cause |
| ︙ | ︙ | |||
87904 87905 87906 87907 87908 87909 87910 | ** ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either ** true or false and is never NULL. If both operands are NULL then the result ** of comparison is true. If either operand is NULL then the result is false. ** If neither operand is NULL the result is the same as it would be if ** the SQLITE_NULLEQ flag were omitted from P5. ** | | | < < < < < | < | 88451 88452 88453 88454 88455 88456 88457 88458 88459 88460 88461 88462 88463 88464 88465 88466 88467 88468 88469 88470 88471 88472 88473 88474 88475 88476 88477 88478 88479 | ** ** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either ** true or false and is never NULL. If both operands are NULL then the result ** of comparison is true. If either operand is NULL then the result is false. ** If neither operand is NULL the result is the same as it would be if ** the SQLITE_NULLEQ flag were omitted from P5. ** ** This opcode saves the result of comparison for use by the new ** OP_Jump opcode. */ /* Opcode: Ne P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]!=r[P1] ** ** This works just like the Eq opcode except that the jump is taken if ** the operands in registers P1 and P3 are not equal. See the Eq opcode for ** additional information. */ /* Opcode: Lt P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]<r[P1] ** ** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then ** jump to address P2. ** ** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or ** reg(P3) is NULL then the take the jump. If the SQLITE_JUMPIFNULL ** bit is clear then fall through if either operand is NULL. ** ** The SQLITE_AFF_MASK portion of P5 must be an affinity character - ** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made |
| ︙ | ︙ | |||
87947 87948 87949 87950 87951 87952 87953 87954 87955 87956 87957 87958 87959 87960 | ** used to determine the results of the comparison. If both values ** are text, then the appropriate collating function specified in ** P4 is used to do the comparison. If P4 is not specified then ** memcmp() is used to compare text string. If both values are ** numeric, then a numeric comparison is used. If the two values ** are of different types, then numbers are considered less than ** strings and strings are considered less than blobs. */ /* Opcode: Le P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]<=r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is less than or equal to the content of ** register P1. See the Lt opcode for additional information. | > > > | 88488 88489 88490 88491 88492 88493 88494 88495 88496 88497 88498 88499 88500 88501 88502 88503 88504 | ** used to determine the results of the comparison. If both values ** are text, then the appropriate collating function specified in ** P4 is used to do the comparison. If P4 is not specified then ** memcmp() is used to compare text string. If both values are ** numeric, then a numeric comparison is used. If the two values ** are of different types, then numbers are considered less than ** strings and strings are considered less than blobs. ** ** This opcode saves the result of comparison for use by the new ** OP_Jump opcode. */ /* Opcode: Le P1 P2 P3 P4 P5 ** Synopsis: IF r[P3]<=r[P1] ** ** This works just like the Lt opcode except that the jump is taken if ** the content of register P3 is less than or equal to the content of ** register P1. See the Lt opcode for additional information. |
| ︙ | ︙ | |||
87984 87985 87986 87987 87988 87989 87990 87991 87992 87993 87994 87995 87996 87997 |
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
** OP_Eq or OP_Ne) then take the jump or not depending on whether
** or not both operands are null.
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > | 88528 88529 88530 88531 88532 88533 88534 88535 88536 88537 88538 88539 88540 88541 88542 88543 88544 88545 88546 88547 88548 88549 88550 88551 88552 88553 88554 88555 88556 88557 88558 88559 88560 88561 88562 88563 88564 88565 88566 |
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
if( (flags1 & flags3 & MEM_Int)!=0 ){
assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
/* Common case of comparison of two integers */
if( pIn3->u.i > pIn1->u.i ){
iCompare = +1;
if( sqlite3aGTb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
}else if( pIn3->u.i < pIn1->u.i ){
iCompare = -1;
if( sqlite3aLTb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
}else{
iCompare = 0;
if( sqlite3aEQb[pOp->opcode] ){
VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
goto jump_to_p2;
}
}
VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
break;
}
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
** OP_Eq or OP_Ne) then take the jump or not depending on whether
** or not both operands are null.
*/
|
| ︙ | ︙ | |||
88006 88007 88008 88009 88010 88011 88012 |
res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
| < < | < < < < | | | < | > < < < < < < < < | 88575 88576 88577 88578 88579 88580 88581 88582 88583 88584 88585 88586 88587 88588 88589 88590 88591 88592 88593 88594 88595 88596 88597 88598 88599 88600 88601 88602 88603 88604 88605 88606 88607 88608 88609 88610 |
res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
iCompare = 1; /* Operands are not equal */
VdbeBranchTaken(2,3);
if( pOp->p5 & SQLITE_JUMPIFNULL ){
goto jump_to_p2;
}
break;
}
}else{
/* Neither operand is NULL and we couldn't do the special high-speed
** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
testcase( flags3==pIn3->flags );
flags3 = pIn3->flags;
}
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn3,0);
}
}
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
testcase( pIn1->flags & MEM_IntReal );
sqlite3VdbeMemStringify(pIn1, encoding, 1);
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
| ︙ | ︙ | |||
88064 88065 88066 88067 88068 88069 88070 |
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
}
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
| | | < | < | < | > < < < < < < < < < < < < < < < < < < < < < < < < | | | | < | | < | | | | < | < | | | 88619 88620 88621 88622 88623 88624 88625 88626 88627 88628 88629 88630 88631 88632 88633 88634 88635 88636 88637 88638 88639 88640 88641 88642 88643 88644 88645 88646 88647 88648 88649 88650 88651 88652 88653 88654 88655 88656 88657 88658 88659 88660 88661 88662 88663 88664 88665 88666 88667 88668 88669 88670 88671 88672 88673 88674 88675 88676 88677 88678 88679 88680 88681 88682 88683 88684 88685 88686 88687 88688 88689 |
testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
}
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
** operator actually is. The next block of code depends on the fact
** that the 6 comparison operators are consecutive integers in this
** order: NE, EQ, GT, LE, LT, GE */
assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
if( res<0 ){
res2 = sqlite3aLTb[pOp->opcode];
}else if( res==0 ){
res2 = sqlite3aEQb[pOp->opcode];
}else{
res2 = sqlite3aGTb[pOp->opcode];
}
iCompare = res;
/* Undo any changes made by applyAffinity() to the input registers. */
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
pIn3->flags = flags3;
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
if( res2 ){
goto jump_to_p2;
}
break;
}
/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
** OP_Lt or OP_Gt.
**
** If result of an OP_Eq comparison on the same two operands as the
** prior OP_Lt or OP_Gt would have been true, then jump to P2.
** If the result of an OP_Eq comparison on the two previous
** operands would have been false or NULL, then fall through.
*/
case OP_ElseEq: { /* same as TK_ESCAPE, jump */
#ifdef SQLITE_DEBUG
/* Verify the preconditions of this opcode - that it follows an OP_Lt or
** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
int iAddr;
for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
break;
}
#endif /* SQLITE_DEBUG */
VdbeBranchTaken(iCompare==0, 2);
if( iCompare==0 ) goto jump_to_p2;
break;
}
/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next
|
| ︙ | ︙ | |||
88460 88461 88462 88463 88464 88465 88466 88467 88468 88469 88470 88471 88472 88473 |
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){
goto jump_to_p2;
}
break;
}
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
| > > > > > > > > > > > > > > > > > > | 88985 88986 88987 88988 88989 88990 88991 88992 88993 88994 88995 88996 88997 88998 88999 89000 89001 89002 89003 89004 89005 89006 89007 89008 89009 89010 89011 89012 89013 89014 89015 89016 |
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){
goto jump_to_p2;
}
break;
}
/* Opcode: ZeroOrNull P1 P2 P3 * *
** Synopsis: r[P2] = 0 OR NULL
**
** If all both registers P1 and P3 are NOT NULL, then store a zero in
** register P2. If either registers P1 or P3 are NULL then put
** a NULL in register P2.
*/
case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
if( (aMem[pOp->p1].flags & MEM_Null)!=0
|| (aMem[pOp->p3].flags & MEM_Null)!=0
){
sqlite3VdbeMemSetNull(aMem + pOp->p2);
}else{
sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
}
break;
}
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
|
| ︙ | ︙ | |||
90412 90413 90414 90415 90416 90417 90418 | UnpackedRecord r; assert( pOp[1].opcode==OP_SeekGE ); /* pOp->p2 points to the first instruction past the OP_IdxGT that ** follows the OP_SeekGE. */ assert( pOp->p2>=(int)(pOp-aOp)+2 ); | | < | 90955 90956 90957 90958 90959 90960 90961 90962 90963 90964 90965 90966 90967 90968 90969 | UnpackedRecord r; assert( pOp[1].opcode==OP_SeekGE ); /* pOp->p2 points to the first instruction past the OP_IdxGT that ** follows the OP_SeekGE. */ assert( pOp->p2>=(int)(pOp-aOp)+2 ); assert( aOp[pOp->p2-1].opcode==OP_IdxGT ); assert( pOp[1].p1==aOp[pOp->p2-1].p1 ); assert( pOp[1].p2==aOp[pOp->p2-1].p2 ); assert( pOp[1].p3==aOp[pOp->p2-1].p3 ); assert( pOp->p1>0 ); pC = p->apCsr[pOp[1].p1]; assert( pC!=0 ); |
| ︙ | ︙ | |||
90517 90518 90519 90520 90521 90522 90523 90524 90525 90526 90527 90528 90529 90530 90531 90532 |
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHit<pOp->p2 ){
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
pC->seekHit = pOp->p3;
}
break;
}
/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2
| > > > > > > > > > > | 91059 91060 91061 91062 91063 91064 91065 91066 91067 91068 91069 91070 91071 91072 91073 91074 91075 91076 91077 91078 91079 91080 91081 91082 91083 91084 |
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHit<pOp->p2 ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
}
#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
}
#endif
pC->seekHit = pOp->p3;
}
break;
}
/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2
|
| ︙ | ︙ | |||
90633 90634 90635 90636 90637 90638 90639 90640 90641 90642 90643 90644 90645 90646 |
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: { /* jump, in3 */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
| > > > > > | 91185 91186 91187 91188 91189 91190 91191 91192 91193 91194 91195 91196 91197 91198 91199 91200 91201 91202 91203 |
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: { /* jump, in3 */
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
if( db->flags&SQLITE_VdbeTrace ){
printf("seekHit is %d\n", pC->seekHit);
}
#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
|
| ︙ | ︙ | |||
91062 91063 91064 91065 91066 91067 91068 |
zDb = 0; /* Not needed. Silence a compiler warning. */
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
| | | 91619 91620 91621 91622 91623 91624 91625 91626 91627 91628 91629 91630 91631 91632 91633 |
zDb = 0; /* Not needed. Silence a compiler warning. */
}
#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);
}
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
/* Prevent post-update hook from running in cases when it should not */
pTab = 0;
}
}
if( pOp->p5 & OPFLAG_ISNOOP ) break;
|
| ︙ | ︙ | |||
91222 91223 91224 91225 91226 91227 91228 |
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,
| | | 91779 91780 91781 91782 91783 91784 91785 91786 91787 91788 91789 91790 91791 91792 91793 |
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,
pOp->p3, -1
);
}
if( opflags & OPFLAG_ISNOOP ) break;
#endif
/* Only flags that can be set are SAVEPOISTION and AUXDELETE */
assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 );
|
| ︙ | ︙ | |||
92168 92169 92170 92171 92172 92173 92174 | ** in the database file is given by P1. But, unlike Destroy, do not ** remove the table or index from the database file. ** ** The table being clear is in the main database file if P2==0. If ** P2==1 then the table to be clear is in the auxiliary database file ** that is used to store tables create using CREATE TEMPORARY TABLE. ** | | < | | | | < < | 92725 92726 92727 92728 92729 92730 92731 92732 92733 92734 92735 92736 92737 92738 92739 92740 92741 92742 92743 92744 92745 92746 92747 92748 92749 92750 92751 92752 92753 |
** in the database file is given by P1. But, unlike Destroy, do not
** remove the table or index from the database file.
**
** The table being clear is in the main database file if P2==0. If
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the P3 value is non-zero, then the row change count is incremented
** by the number of rows in the table being cleared. If P3 is greater
** than zero, then the value stored in register P3 is also incremented
** by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
int nChange;
sqlite3VdbeIncrWriteCounter(p, 0);
nChange = 0;
assert( p->readOnly==0 );
assert( DbMaskTest(p->btreeMask, pOp->p2) );
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange);
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
assert( memIsValid(&aMem[pOp->p3]) );
memAboutToChange(p, &aMem[pOp->p3]);
aMem[pOp->p3].u.i += nChange;
}
|
| ︙ | ︙ | |||
92291 92292 92293 92294 92295 92296 92297 |
for(iDb=0; iDb<db->nDb; iDb++){
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
}
#endif
iDb = pOp->p1;
assert( iDb>=0 && iDb<db->nDb );
| | | 92845 92846 92847 92848 92849 92850 92851 92852 92853 92854 92855 92856 92857 92858 92859 |
for(iDb=0; iDb<db->nDb; iDb++){
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
}
#endif
iDb = pOp->p1;
assert( iDb>=0 && iDb<db->nDb );
assert( DbHasProperty(db, iDb, DB_SchemaLoaded) || db->mallocFailed );
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
|
| ︙ | ︙ | |||
93173 93174 93175 93176 93177 93178 93179 93180 93181 93182 93183 93184 93185 93186 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); eOld = sqlite3PagerGetJournalMode(pPager); if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; #ifndef SQLITE_OMIT_WAL zFilename = sqlite3PagerFilename(pPager, 1); /* Do not allow a transition to journal_mode=WAL for a database ** in temporary storage or if the VFS does not support shared memory | > | 93727 93728 93729 93730 93731 93732 93733 93734 93735 93736 93737 93738 93739 93740 93741 | assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( p->readOnly==0 ); pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); eOld = sqlite3PagerGetJournalMode(pPager); if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld; assert( sqlite3BtreeHoldsMutex(pBt) ); if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld; #ifndef SQLITE_OMIT_WAL zFilename = sqlite3PagerFilename(pPager, 1); /* Do not allow a transition to journal_mode=WAL for a database ** in temporary storage or if the VFS does not support shared memory |
| ︙ | ︙ | |||
94651 94652 94653 94654 94655 94656 94657 |
** 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(
| | | 95206 95207 95208 95209 95210 95211 95212 95213 95214 95215 95216 95217 95218 95219 95220 |
** 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);
sqlite3BtreeLeaveCursor(p->pCsr);
if( rc==SQLITE_ABORT ){
|
| ︙ | ︙ | |||
94722 94723 94724 94725 94726 94727 94728 94729 94730 94731 94732 94733 94734 94735 |
if( p->pStmt==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
char *zErr;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
}
assert( rc!=SQLITE_SCHEMA );
}
| > | 95277 95278 95279 95280 95281 95282 95283 95284 95285 95286 95287 95288 95289 95290 95291 |
if( p->pStmt==0 ){
/* If there is no statement handle, then the blob-handle has
** already been invalidated. Return SQLITE_ABORT in this case.
*/
rc = SQLITE_ABORT;
}else{
char *zErr;
((Vdbe*)p->pStmt)->rc = SQLITE_OK;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
}
assert( rc!=SQLITE_SCHEMA );
}
|
| ︙ | ︙ | |||
98192 98193 98194 98195 98196 98197 98198 |
}
/*
** Truncate the in-memory file.
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
| > > | < | | | | | | | | | | | | | | | | | > | 98748 98749 98750 98751 98752 98753 98754 98755 98756 98757 98758 98759 98760 98761 98762 98763 98764 98765 98766 98767 98768 98769 98770 98771 98772 98773 98774 98775 98776 98777 98778 98779 98780 98781 98782 98783 |
}
/*
** Truncate the in-memory file.
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 );
if( size<p->endpoint.iOffset ){
FileChunk *pIter = 0;
if( size==0 ){
memjrnlFreeChunks(p->pFirst);
p->pFirst = 0;
}else{
i64 iOff = p->nChunkSize;
for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){
iOff += p->nChunkSize;
}
if( ALWAYS(pIter) ){
memjrnlFreeChunks(pIter->pNext);
pIter->pNext = 0;
}
}
p->endpoint.pChunk = pIter;
p->endpoint.iOffset = size;
p->readpoint.pChunk = 0;
p->readpoint.iOffset = 0;
}
return SQLITE_OK;
}
/*
** Close the file.
*/
static int memjrnlClose(sqlite3_file *pJfd){
|
| ︙ | ︙ | |||
98404 98405 98406 98407 98408 98409 98410 |
int rc;
rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
| < < < < < | | | 98962 98963 98964 98965 98966 98967 98968 98969 98970 98971 98972 98973 98974 98975 98976 98977 98978 98979 |
int rc;
rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pStart);
if( rc ) return WRC_Abort;
rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
if( rc ) return WRC_Abort;
if( bOneOnly ) break;
}
return WRC_Continue;
}
#endif
/*
|
| ︙ | ︙ | |||
98488 98489 98490 98491 98492 98493 98494 98495 98496 98497 98498 98499 98500 98501 98502 98503 98504 98505 98506 98507 98508 |
if( p ){
for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
}
}
return WRC_Continue;
}
/*
** Walk all expressions associated with SELECT statement p. Do
** not invoke the SELECT callback on p, but do (of course) invoke
** any expr callbacks and SELECT callbacks that come from subqueries.
** Return WRC_Abort or WRC_Continue.
*/
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
| > > > > > > > > > > | < > | > | > > > > | 99041 99042 99043 99044 99045 99046 99047 99048 99049 99050 99051 99052 99053 99054 99055 99056 99057 99058 99059 99060 99061 99062 99063 99064 99065 99066 99067 99068 99069 99070 99071 99072 99073 99074 99075 99076 99077 99078 99079 99080 99081 99082 99083 99084 99085 99086 99087 |
if( p ){
for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
}
}
return WRC_Continue;
}
/*
** This is a no-op callback for Walker->xSelectCallback2. If this
** callback is set, then the Select->pWinDefn list is traversed.
*/
SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker *pWalker, Select *p){
UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(p);
/* No-op */
}
/*
** Walk all expressions associated with SELECT statement p. Do
** not invoke the SELECT callback on p, but do (of course) invoke
** any expr callbacks and SELECT callbacks that come from subqueries.
** Return WRC_Abort or WRC_Continue.
*/
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
#if !defined(SQLITE_OMIT_WINDOWFUNC)
if( p->pWinDefn ){
Parse *pParse;
if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
|| ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
#ifndef SQLITE_OMIT_CTE
|| pWalker->xSelectCallback2==sqlite3SelectPopWith
#endif
){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
int rc = walkWindowList(pWalker, p->pWinDefn, 0);
return rc;
}
}
#endif
|
| ︙ | ︙ | |||
98529 98530 98531 98532 98533 98534 98535 |
*/
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcList *pSrc;
int i;
SrcItem *pItem;
pSrc = p->pSrc;
| | | 99097 99098 99099 99100 99101 99102 99103 99104 99105 99106 99107 99108 99109 99110 99111 |
*/
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcList *pSrc;
int i;
SrcItem *pItem;
pSrc = p->pSrc;
if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
}
if( pItem->fg.isTabFunc
&& sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
){
|
| ︙ | ︙ | |||
98703 98704 98705 98706 98707 98708 98709 | sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); | > > | > | 99271 99272 99273 99274 99275 99276 99277 99278 99279 99280 99281 99282 99283 99284 99285 99286 99287 99288 |
sqlite3 *db; /* The database connection */
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
db = pParse->db;
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,
|
| ︙ | ︙ | |||
98725 98726 98727 98728 98729 98730 98731 |
memcpy(pExpr, pDup, sizeof(*pExpr));
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags |= EP_MemToken;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
| | < < | 99296 99297 99298 99299 99300 99301 99302 99303 99304 99305 99306 99307 99308 99309 99310 99311 |
memcpy(pExpr, pDup, sizeof(*pExpr));
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
pExpr->flags |= EP_MemToken;
}
if( ExprHasProperty(pExpr, EP_WinFunc) ){
if( ALWAYS(pExpr->y.pWin!=0) ){
pExpr->y.pWin->pOwner = pExpr;
}
}
sqlite3DbFree(db, pDup);
}
}
|
| ︙ | ︙ | |||
98998 98999 99000 99001 99002 99003 99004 |
*/
if( cnt==0 && zDb==0 ){
pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
| > > > > > > > | < < < | 99567 99568 99569 99570 99571 99572 99573 99574 99575 99576 99577 99578 99579 99580 99581 99582 99583 99584 99585 99586 99587 99588 99589 99590 99591 99592 99593 |
*/
if( cnt==0 && zDb==0 ){
pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
if( pParse->bReturning ){
if( (pNC->ncFlags & NC_UBaseReg)!=0
&& (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
){
pExpr->iTable = op!=TK_DELETE;
pTab = pParse->pTriggerTab;
}
}else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
pTab = pParse->pTriggerTab;
}else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
|
| ︙ | ︙ | |||
99116 99117 99118 99119 99120 99121 99122 |
**
** The ability to use an output result-set column in the WHERE, GROUP BY,
** or HAVING clauses, or as part of a larger expression in the ORDER BY
** clause is not standard SQL. This is a (goofy) SQLite extension, that
** is supported for backwards compatibility only. Hence, we issue a warning
** on sqlite3_log() whenever the capability is used.
*/
| > | < | 99689 99690 99691 99692 99693 99694 99695 99696 99697 99698 99699 99700 99701 99702 99703 99704 |
**
** The ability to use an output result-set column in the WHERE, GROUP BY,
** or HAVING clauses, or as part of a larger expression in the ORDER BY
** clause is not standard SQL. This is a (goofy) SQLite extension, that
** is supported for backwards compatibility only. Hence, we issue a warning
** on sqlite3_log() whenever the capability is used.
*/
if( cnt==0
&& (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
if( pEList->a[j].eEName==ENAME_NAME
|
| ︙ | ︙ | |||
99181 99182 99183 99184 99185 99186 99187 |
** Because no reference was made to outer contexts, the pNC->nRef
** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 ){
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted)
&& areDoubleQuotedStringsEnabled(db, pTopNC)
| < < < < < < | 99754 99755 99756 99757 99758 99759 99760 99761 99762 99763 99764 99765 99766 99767 99768 99769 99770 99771 99772 99773 99774 99775 99776 99777 99778 99779 99780 99781 |
** Because no reference was made to outer contexts, the pNC->nRef
** fields are not changed in any context.
*/
if( cnt==0 && zTab==0 ){
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted)
&& areDoubleQuotedStringsEnabled(db, pTopNC)
){
/* If a double-quoted identifier does not match any known column name,
** then treat it as a string.
**
** This hack was added in the early days of SQLite in a misguided attempt
** to be compatible with MySQL 3.x, which used double-quotes for strings.
** I now sorely regret putting in this hack. The effect of this hack is
** that misspelled identifier names are silently converted into strings
** rather than causing an error, to the frustration of countless
** programmers. To all those frustrated programmers, my apologies.
**
** Someday, I hope to get rid of this hack. Unfortunately there is
** a huge amount of legacy SQL that uses it. So for now, we just
** issue a warning.
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
pExpr->op = TK_STRING;
|
| ︙ | ︙ | |||
99231 99232 99233 99234 99235 99236 99237 |
sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
}else if( zTab ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
pParse->checkSchema = 1;
| | | 99798 99799 99800 99801 99802 99803 99804 99805 99806 99807 99808 99809 99810 99811 99812 |
sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
}else if( zTab ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
pParse->checkSchema = 1;
pTopNC->nNcErr++;
}
/* If a column from a table in pSrcList is referenced, then record
** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is
** set if the 63rd or any subsequent column is used.
**
|
| ︙ | ︙ | |||
99538 99539 99540 99541 99542 99543 99544 |
ExprSetProperty(pExpr, EP_Unlikely);
if( n==2 ){
pExpr->iTable = exprProbability(pList->a[1].pExpr);
if( pExpr->iTable<0 ){
sqlite3ErrorMsg(pParse,
"second argument to likelihood() must be a "
"constant between 0.0 and 1.0");
| | | 100105 100106 100107 100108 100109 100110 100111 100112 100113 100114 100115 100116 100117 100118 100119 |
ExprSetProperty(pExpr, EP_Unlikely);
if( n==2 ){
pExpr->iTable = exprProbability(pList->a[1].pExpr);
if( pExpr->iTable<0 ){
sqlite3ErrorMsg(pParse,
"second argument to likelihood() must be a "
"constant between 0.0 and 1.0");
pNC->nNcErr++;
}
}else{
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
** equivalent to likelihood(X, 0.0625).
** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
** short-hand for likelihood(X,0.0625).
** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
|
| ︙ | ︙ | |||
99560 99561 99562 99563 99564 99565 99566 |
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
if( auth!=SQLITE_OK ){
if( auth==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
pDef->zName);
| | | 100127 100128 100129 100130 100131 100132 100133 100134 100135 100136 100137 100138 100139 100140 100141 |
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
if( auth!=SQLITE_OK ){
if( auth==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
pDef->zName);
pNC->nNcErr++;
}
pExpr->op = TK_NULL;
return WRC_Prune;
}
}
#endif
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
| ︙ | ︙ | |||
99616 99617 99618 99619 99620 99621 99622 |
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
if( pDef && pDef->xValue==0 && pWin ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
| | | | | | | | 100183 100184 100185 100186 100187 100188 100189 100190 100191 100192 100193 100194 100195 100196 100197 100198 100199 100200 100201 100202 100203 100204 100205 100206 100207 100208 100209 100210 100211 100212 100213 100214 100215 100216 100217 100218 100219 100220 100221 100222 100223 100224 100225 100226 100227 100228 100229 100230 100231 100232 100233 100234 100235 100236 100237 100238 |
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
if( pDef && pDef->xValue==0 && pWin ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
pNC->nNcErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
|| (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0)
){
const char *zType;
if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
zType = "window";
}else{
zType = "aggregate";
}
sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
pNC->nNcErr++;
is_agg = 0;
}
#else
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
pNC->nNcErr++;
is_agg = 0;
}
#endif
else if( no_such_func && pParse->db->init.busy==0
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
&& pParse->explain==0
#endif
){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
pNC->nNcErr++;
}else if( wrong_num_args ){
sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
nId, zId);
pNC->nNcErr++;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ErrorMsg(pParse,
"FILTER may not be used with non-aggregate %.*s()",
nId, zId
);
pNC->nNcErr++;
}
#endif
if( is_agg ){
/* Window functions may not be arguments of aggregate functions.
** Or arguments of other window functions. But aggregate functions
** may be arguments for window functions. */
#ifndef SQLITE_OMIT_WINDOWFUNC
|
| ︙ | ︙ | |||
99881 99882 99883 99884 99885 99886 99887 | /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; | | | | | 100448 100449 100450 100451 100452 100453 100454 100455 100456 100457 100458 100459 100460 100461 100462 100463 100464 100465 100466 | /* Resolve all names in the ORDER BY term expression */ memset(&nc, 0, sizeof(nc)); nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect; nc.nNcErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; db->suppressErr = 1; rc = sqlite3ResolveExprNames(&nc, pE); db->suppressErr = savedSuppErr; if( rc ) return 0; /* Try to match the ORDER BY expression against an expression ** in the result set. Return an 1-based index of the matching ** result-set entry. |
| ︙ | ︙ | |||
99984 99985 99986 99987 99988 99989 99990 |
/* Now test if expression pE matches one of the values returned
** by pSelect. In the usual case this is done by duplicating the
** expression, resolving any symbols in it, and then comparing
** it against each expression returned by the SELECT statement.
** Once the comparisons are finished, the duplicate expression
** is deleted.
**
| | | < < | | < < < | < > > | < < > | | 100551 100552 100553 100554 100555 100556 100557 100558 100559 100560 100561 100562 100563 100564 100565 100566 100567 100568 100569 100570 100571 100572 100573 100574 100575 100576 100577 100578 100579 100580 100581 100582 |
/* Now test if expression pE matches one of the values returned
** by pSelect. In the usual case this is done by duplicating the
** expression, resolving any symbols in it, and then comparing
** it against each expression returned by the SELECT statement.
** Once the comparisons are finished, the duplicate expression
** is deleted.
**
** If this is running as part of an ALTER TABLE operation and
** the symbols resolve successfully, also resolve the symbols in the
** actual expression. This allows the code in alter.c to modify
** column references within the ORDER BY expression as required. */
pDup = sqlite3ExprDup(db, pE, 0);
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
if( IN_RENAME_OBJECT && iCol>0 ){
resolveOrderByTermToExprList(pParse, pSelect, pE);
}
}
sqlite3ExprDelete(db, pDup);
}
}
if( iCol>0 ){
/* Convert the ORDER BY term into an integer column number iCol,
** taking care to preserve the COLLATE clause if it exists. */
if( !IN_RENAME_OBJECT ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return 1;
pNew->flags |= EP_IntValue;
pNew->u.iValue = iCol;
if( pItem->pExpr==pE ){
pItem->pExpr = pNew;
|
| ︙ | ︙ | |||
100141 100142 100143 100144 100145 100146 100147 |
){
int i, j; /* Loop counters */
int iCol; /* Column number */
struct ExprList_item *pItem; /* A term of the ORDER BY clause */
Parse *pParse; /* Parsing context */
int nResult; /* Number of terms in the result set */
| | | 100703 100704 100705 100706 100707 100708 100709 100710 100711 100712 100713 100714 100715 100716 100717 |
){
int i, j; /* Loop counters */
int iCol; /* Column number */
struct ExprList_item *pItem; /* A term of the ORDER BY clause */
Parse *pParse; /* Parsing context */
int nResult; /* Number of terms in the result set */
assert( pOrderBy!=0 );
nResult = pSelect->pEList->nExpr;
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
if( NEVER(pE2==0) ) continue;
if( zType[0]!='G' ){
|
| ︙ | ︙ | |||
100231 100232 100233 100234 100235 100236 100237 100238 100239 100240 100241 100242 100243 100244 100245 |
isCompound = p->pPrior!=0;
nCompound = 0;
pLeftmost = p;
while( p ){
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
p->selFlags |= SF_Resolved;
/* Resolve the expressions in the LIMIT and OFFSET clauses. These
** are not allowed to refer to any names, so pass an empty NameContext.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pWinSelect = p;
| > > | 100793 100794 100795 100796 100797 100798 100799 100800 100801 100802 100803 100804 100805 100806 100807 100808 100809 |
isCompound = p->pPrior!=0;
nCompound = 0;
pLeftmost = p;
while( p ){
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */
p->selFlags |= SF_Resolved;
/* Resolve the expressions in the LIMIT and OFFSET clauses. These
** are not allowed to refer to any names, so pass an empty NameContext.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pWinSelect = p;
|
| ︙ | ︙ | |||
100306 100307 100308 100309 100310 100311 100312 |
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
assert( NC_MinMaxAgg==SF_MinMaxAgg );
p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
| < < < < < < < > > > > > | > > > > > > > > > > > > > > | 100870 100871 100872 100873 100874 100875 100876 100877 100878 100879 100880 100881 100882 100883 100884 100885 100886 100887 100888 100889 100890 100891 100892 100893 100894 100895 100896 100897 100898 100899 100900 100901 100902 100903 100904 100905 100906 100907 100908 100909 100910 100911 100912 100913 100914 100915 100916 100917 100918 100919 100920 100921 100922 100923 100924 100925 |
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
assert( NC_MinMaxAgg==SF_MinMaxAgg );
p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
/* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
** aliases in the result set.
**
** Minor point: If this is the case, then the expression will be
** re-evaluated for each reference to it.
*/
assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
if( p->pHaving ){
if( !pGroupBy ){
sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
return WRC_Abort;
}
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
}
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
/* Resolve names in table-valued-function arguments */
for(i=0; i<p->pSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
if( pItem->fg.isTabFunc
&& sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
){
return WRC_Abort;
}
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( IN_RENAME_OBJECT ){
Window *pWin;
for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
|| sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
){
return WRC_Abort;
}
}
}
#endif
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
*/
sNC.pNext = 0;
sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
|
| ︙ | ︙ | |||
100364 100365 100366 100367 100368 100369 100370 |
** the compound have been resolved.
**
** If there is an ORDER BY clause on a term of a compound-select other
** than the right-most term, then that is a syntax error. But the error
** is not detected until much later, and so we need to go ahead and
** resolve those symbols on the incorrect ORDER BY for consistency.
*/
| > | | 100940 100941 100942 100943 100944 100945 100946 100947 100948 100949 100950 100951 100952 100953 100954 100955 |
** the compound have been resolved.
**
** If there is an ORDER BY clause on a term of a compound-select other
** than the right-most term, then that is a syntax error. But the error
** is not detected until much later, and so we need to go ahead and
** resolve those symbols on the incorrect ORDER BY for consistency.
*/
if( p->pOrderBy!=0
&& isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
){
return WRC_Abort;
}
if( db->mallocFailed ){
return WRC_Abort;
}
|
| ︙ | ︙ | |||
100392 100393 100394 100395 100396 100397 100398 |
sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
"the GROUP BY clause");
return WRC_Abort;
}
}
}
| < < < < < < < < < < < < < | 100969 100970 100971 100972 100973 100974 100975 100976 100977 100978 100979 100980 100981 100982 |
sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
"the GROUP BY clause");
return WRC_Abort;
}
}
}
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
sqlite3SelectWrongNumTermsError(pParse, p->pNext);
return WRC_Abort;
}
|
| ︙ | ︙ | |||
100488 100489 100490 100491 100492 100493 100494 | Walker w; if( pExpr==0 ) return SQLITE_OK; savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin); pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin); w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; | | | | 101052 101053 101054 101055 101056 101057 101058 101059 101060 101061 101062 101063 101064 101065 101066 101067 101068 101069 101070 101071 101072 101073 101074 101075 101076 101077 101078 101079 101080 101081 101082 101083 101084 101085 |
Walker w;
if( pExpr==0 ) return SQLITE_OK;
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight += pExpr->nHeight;
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
return SQLITE_ERROR;
}
#endif
sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight -= pExpr->nHeight;
#endif
assert( EP_Agg==NC_HasAgg );
assert( EP_Win==NC_HasWin );
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
pNC->ncFlags |= savedHasAgg;
return pNC->nNcErr>0 || w.pParse->nErr>0;
}
/*
** Resolve all names for all expression in an expression list. This is
** just like sqlite3ResolveExprNames() except that it works for an expression
** list rather than a single expression.
*/
|
| ︙ | ︙ | |||
100552 100553 100554 100555 100556 100557 100558 |
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
}
| | | 101116 101117 101118 101119 101120 101121 101122 101123 101124 101125 101126 101127 101128 101129 101130 |
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
}
if( w.pParse->nErr>0 ) return WRC_Abort;
}
pNC->ncFlags |= savedHasAgg;
return WRC_Continue;
}
/*
** Resolve all names in all expressions of a SELECT and in all
|
| ︙ | ︙ | |||
100695 100696 100697 100698 100699 100700 100701 100702 100703 100704 100705 100706 100707 100708 |
assert( pExpr->op==TK_COLLATE
|| 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_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
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);
}
| > > > > < < < < | 101259 101260 101261 101262 101263 101264 101265 101266 101267 101268 101269 101270 101271 101272 101273 101274 101275 101276 101277 101278 101279 101280 101281 101282 101283 101284 101285 101286 101287 101288 101289 |
assert( pExpr->op==TK_COLLATE
|| 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) && pExpr->y.pTab ){
return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
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->flags&EP_xIsSelect );
return sqlite3ExprAffinity(
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
if( op==TK_VECTOR ){
|
| ︙ | ︙ | |||
100738 100739 100740 100741 100742 100743 100744 |
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
| < < < < < < < < < < < | | 101302 101303 101304 101305 101306 101307 101308 101309 101310 101311 101312 101313 101314 101315 101316 |
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
){
if( pCollName->n>0 ){
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
pNew->flags |= EP_Collate|EP_Skip;
pExpr = pNew;
}
}
|
| ︙ | ︙ | |||
101099 101100 101101 101102 101103 101104 101105 |
**
** If the vector is a (SELECT ...) then the expression returned is
** just the expression for the i-th term of the result set, and may
** not be ready for evaluation because the table cursor has not yet
** been positioned.
*/
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
| | | 101652 101653 101654 101655 101656 101657 101658 101659 101660 101661 101662 101663 101664 101665 101666 |
**
** If the vector is a (SELECT ...) then the expression returned is
** just the expression for the i-th term of the result set, and may
** not be ready for evaluation because the table cursor has not yet
** 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;
}
|
| ︙ | ︙ | |||
101215 101216 101217 101218 101219 101220 101221 |
Expr *pVector, /* Vector to extract element from */
int iField, /* Field to extract from pVector */
int regSelect, /* First in array of registers */
Expr **ppExpr, /* OUT: Expression element */
int *pRegFree /* OUT: Temp register to free */
){
u8 op = pVector->op;
| | > | | > > | 101768 101769 101770 101771 101772 101773 101774 101775 101776 101777 101778 101779 101780 101781 101782 101783 101784 101785 101786 101787 101788 101789 101790 101791 101792 101793 101794 101795 |
Expr *pVector, /* Vector to extract element from */
int iField, /* Field to extract from pVector */
int regSelect, /* First in array of registers */
Expr **ppExpr, /* OUT: Expression element */
int *pRegFree /* OUT: Temp register to free */
){
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;
}
/*
** Expression pExpr is a comparison between two vector values. Compute
** the result of the comparison (1, 0, or NULL) and write that
** result into register dest.
**
|
| ︙ | ︙ | |||
101254 101255 101256 101257 101258 101259 101260 101261 101262 101263 101264 101265 101266 101267 101268 101269 101270 101271 101272 101273 101274 101275 101276 101277 101278 101279 |
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
int nLeft = sqlite3ExprVectorSize(pLeft);
int i;
int regLeft = 0;
int regRight = 0;
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
}
assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
|| pExpr->op==TK_IS || pExpr->op==TK_ISNOT
|| pExpr->op==TK_LT || pExpr->op==TK_GT
|| pExpr->op==TK_LE || pExpr->op==TK_GE
);
assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
|| (pExpr->op==TK_ISNOT && op==TK_NE) );
assert( p5==0 || pExpr->op!=op );
assert( p5==SQLITE_NULLEQ || pExpr->op==op );
| > < | | > > | > > | > > > > > > > > > > < < < | < | < < < < > > > > | 101810 101811 101812 101813 101814 101815 101816 101817 101818 101819 101820 101821 101822 101823 101824 101825 101826 101827 101828 101829 101830 101831 101832 101833 101834 101835 101836 101837 101838 101839 101840 101841 101842 101843 101844 101845 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 101889 101890 101891 101892 101893 101894 101895 |
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
int nLeft = sqlite3ExprVectorSize(pLeft);
int i;
int regLeft = 0;
int regRight = 0;
u8 opx = op;
int addrCmp = 0;
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
}
assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
|| pExpr->op==TK_IS || pExpr->op==TK_ISNOT
|| pExpr->op==TK_LT || pExpr->op==TK_GT
|| pExpr->op==TK_LE || pExpr->op==TK_GE
);
assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
|| (pExpr->op==TK_ISNOT && op==TK_NE) );
assert( p5==0 || pExpr->op!=op );
assert( p5==SQLITE_NULLEQ || pExpr->op==op );
if( op==TK_LE ) opx = TK_LT;
if( op==TK_GE ) opx = TK_GT;
if( op==TK_NE ) opx = TK_EQ;
regLeft = exprCodeSubselect(pParse, pLeft);
regRight = exprCodeSubselect(pParse, pRight);
sqlite3VdbeAddOp2(v, OP_Integer, 1, dest);
for(i=0; 1 /*Loop exits by "break"*/; i++){
int regFree1 = 0, regFree2 = 0;
Expr *pL = 0, *pR = 0;
int r1, r2;
assert( i>=0 && i<nLeft );
if( addrCmp ) sqlite3VdbeJumpHere(v, addrCmp);
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2);
addrCmp = sqlite3VdbeCurrentAddr(v);
codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted);
testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
if( (opx==TK_LT || opx==TK_GT) && i<nLeft-1 ){
addrCmp = sqlite3VdbeAddOp0(v, OP_ElseEq);
testcase(opx==TK_LT); VdbeCoverageIf(v,opx==TK_LT);
testcase(opx==TK_GT); VdbeCoverageIf(v,opx==TK_GT);
}
if( p5==SQLITE_NULLEQ ){
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest);
}else{
sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, dest, r2);
}
if( i==nLeft-1 ){
break;
}
if( opx==TK_EQ ){
sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v);
}else{
assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
if( i==nLeft-2 ) opx = op;
}
}
sqlite3VdbeJumpHere(v, addrCmp);
sqlite3VdbeResolveLabel(v, addrDone);
if( op==TK_NE ){
sqlite3VdbeAddOp2(v, OP_Not, dest, dest);
}
}
#if SQLITE_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
|
| ︙ | ︙ | |||
101601 101602 101603 101604 101605 101606 101607 |
if( pLeft==0 ){
return pRight;
}else if( pRight==0 ){
return pLeft;
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
| | | | 102167 102168 102169 102170 102171 102172 102173 102174 102175 102176 102177 102178 102179 102180 102181 102182 |
if( pLeft==0 ){
return pRight;
}else if( pRight==0 ){
return pLeft;
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
sqlite3ExprDeferredDelete(pParse, pLeft);
sqlite3ExprDeferredDelete(pParse, pRight);
return sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
}
}
/*
|
| ︙ | ︙ | |||
101799 101800 101801 101802 101803 101804 101805 101806 101807 101808 101809 101810 101811 101812 |
sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
if( p ){
if( IN_RENAME_OBJECT ){
sqlite3RenameExprUnmap(pParse, p);
| > > > > > > > > > > > > > > > > | 102365 102366 102367 102368 102369 102370 102371 102372 102373 102374 102375 102376 102377 102378 102379 102380 102381 102382 102383 102384 102385 102386 102387 102388 102389 102390 102391 102392 102393 102394 |
sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p ) sqlite3ExprDeleteNN(db, p);
}
/*
** Arrange to cause pExpr to be deleted when the pParse is deleted.
** This is similar to sqlite3ExprDelete() except that the delete is
** deferred untilthe pParse is deleted.
**
** The pExpr might be deleted immediately on an OOM error.
**
** The deferred delete is (currently) implemented by adding the
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
pParse->pConstExpr =
sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}
/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
if( p ){
if( IN_RENAME_OBJECT ){
sqlite3RenameExprUnmap(pParse, p);
|
| ︙ | ︙ | |||
101941 101942 101943 101944 101945 101946 101947 101948 101949 101950 101951 101952 101953 101954 |
assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
}
pNew = (Expr *)zAlloc;
if( pNew ){
| > | 102523 102524 102525 102526 102527 102528 102529 102530 102531 102532 102533 102534 102535 102536 102537 |
assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
assert( zAlloc!=0 );
}else{
zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
}
pNew = (Expr *)zAlloc;
if( pNew ){
|
| ︙ | ︙ | |||
102019 102020 102021 102022 102023 102024 102025 |
*pzBuffer = zAlloc;
}
}else{
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
| | > | 102602 102603 102604 102605 102606 102607 102608 102609 102610 102611 102612 102613 102614 102615 102616 102617 |
*pzBuffer = zAlloc;
}
}else{
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
assert( p->iColumn==0 || p->pRight==0 );
assert( p->pRight==0 || p->pRight==p->pLeft
|| ExprHasProperty(p->pLeft, EP_Subquery) );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
}
|
| ︙ | ︙ | |||
102121 102122 102123 102124 102125 102126 102127 102128 102129 102130 102131 102132 102133 102134 102135 102136 102137 102138 102139 |
int i;
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
if( pOldExpr
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
| > | > | 102705 102706 102707 102708 102709 102710 102711 102712 102713 102714 102715 102716 102717 102718 102719 102720 102721 102722 102723 102724 102725 102726 102727 102728 102729 102730 102731 102732 102733 |
int i;
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
pNew->nAlloc = p->nAlloc;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
if( pOldExpr
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
assert( pNewExpr->iColumn==0 || i>0 );
if( pNewExpr->iColumn==0 ){
assert( pOldExpr->pLeft==pOldExpr->pRight
|| ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
}else{
assert( i>0 );
assert( pItem[-1].pExpr!=0 );
assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
pNewExpr->pLeft = pPriorSelectCol;
|
| ︙ | ︙ | |||
102263 102264 102265 102266 102267 102268 102269 102270 102271 102272 102273 102274 102275 102276 |
pNew->pWith = withDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
}
return pRet;
}
| > > > > > > > > | 102849 102850 102851 102852 102853 102854 102855 102856 102857 102858 102859 102860 102861 102862 102863 102864 102865 102866 102867 102868 102869 102870 |
pNew->pWith = withDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
if( db->mallocFailed ){
/* Any prior OOM might have left the Select object incomplete.
** Delete the whole thing rather than allow an incomplete Select
** to be used by the code generator. */
pNew->pNext = 0;
sqlite3SelectDelete(db, pNew);
break;
}
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
}
return pRet;
}
|
| ︙ | ︙ | |||
102293 102294 102295 102296 102297 102298 102299 | ** is a power of two. That is true for sqlite3ExprListAppend() returns ** but is not necessarily true from the return value of sqlite3ExprListDup(). ** ** If a memory allocation error occurs, the entire list is freed and ** NULL is returned. If non-NULL is returned, then it is guaranteed ** that the new entry was successfully appended. */ | > | | < | | < | | > | | > | | > > > > > > > > > > | > | | | > > > | > | > > > | > > > > > > > > > > > > < < | < < < < < < | 102887 102888 102889 102890 102891 102892 102893 102894 102895 102896 102897 102898 102899 102900 102901 102902 102903 102904 102905 102906 102907 102908 102909 102910 102911 102912 102913 102914 102915 102916 102917 102918 102919 102920 102921 102922 102923 102924 102925 102926 102927 102928 102929 102930 102931 102932 102933 102934 102935 102936 102937 102938 102939 102940 102941 102942 102943 102944 102945 102946 102947 102948 102949 102950 102951 102952 102953 102954 102955 102956 102957 102958 |
** is a power of two. That is true for sqlite3ExprListAppend() returns
** but is not necessarily true from the return value of sqlite3ExprListDup().
**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
static const struct ExprList_item zeroItem = {0};
SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
sqlite3 *db, /* Database handle. Used for memory allocation */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
ExprList *pList;
pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
if( pList==0 ){
sqlite3ExprDelete(db, pExpr);
return 0;
}
pList->nAlloc = 4;
pList->nExpr = 1;
pItem = &pList->a[0];
*pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
}
SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
sqlite3 *db, /* Database handle. Used for memory allocation */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
ExprList *pNew;
pList->nAlloc *= 2;
pNew = sqlite3DbRealloc(db, pList,
sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
if( pNew==0 ){
sqlite3ExprListDelete(db, pList);
sqlite3ExprDelete(db, pExpr);
return 0;
}else{
pList = pNew;
}
pItem = &pList->a[pList->nExpr++];
*pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
}
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
if( pList==0 ){
return sqlite3ExprListAppendNew(pParse->db,pExpr);
}
if( pList->nAlloc<pList->nExpr+1 ){
return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr);
}
pItem = &pList->a[pList->nExpr++];
*pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
}
/*
** pColumns and pExpr form a vector assignment which is part of the SET
** clause of an UPDATE statement. Like this:
**
** (a,b,c) = (expr1,expr2,expr3)
|
| ︙ | ︙ | |||
102940 102941 102942 102943 102944 102945 102946 102947 102948 102949 102950 102951 102952 102953 102954 102955 |
** be a small performance hit but is otherwise harmless. On the other
** hand, a false negative (returning FALSE when the result could be NULL)
** will likely result in an incorrect answer. So when in doubt, return
** TRUE.
*/
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
switch( op ){
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
| > > | 103557 103558 103559 103560 103561 103562 103563 103564 103565 103566 103567 103568 103569 103570 103571 103572 103573 103574 |
** be a small performance hit but is otherwise harmless. On the other
** hand, a false negative (returning FALSE when the result could be NULL)
** will likely result in an incorrect answer. So when in doubt, return
** TRUE.
*/
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
assert( p!=0 );
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
assert( p!=0 );
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
switch( op ){
case TK_INTEGER:
case TK_STRING:
case TK_FLOAT:
|
| ︙ | ︙ | |||
103573 103574 103575 103576 103577 103578 103579 103580 103581 103582 103583 103584 103585 103586 |
ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
addrOnce?"":"CORRELATED ", pSelect->selId
));
/* If the LHS and RHS of the IN operator do not match, that
** error will have been caught long before we reach this point. */
if( ALWAYS(pEList->nExpr==nVal) ){
SelectDest dest;
int i;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
| > > > | > | > < | 104192 104193 104194 104195 104196 104197 104198 104199 104200 104201 104202 104203 104204 104205 104206 104207 104208 104209 104210 104211 104212 104213 104214 104215 104216 104217 104218 104219 104220 104221 104222 |
ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
addrOnce?"":"CORRELATED ", pSelect->selId
));
/* If the LHS and RHS of the IN operator do not match, that
** error will have been caught long before we reach this point. */
if( ALWAYS(pEList->nExpr==nVal) ){
Select *pCopy;
SelectDest dest;
int i;
int rc;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3DbFree(pParse->db, dest.zAffSdst);
if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
}
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
for(i=0; i<nVal; i++){
Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
|
| ︙ | ︙ | |||
103684 103685 103686 103687 103688 103689 103690 103691 103692 103693 103694 103695 103696 103697 103698 103699 103700 103701 103702 103703 103704 103705 103706 103707 |
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */
Expr *pLimit; /* New limit expression */
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
pSel = pExpr->x.pSelect;
/* The evaluation of the EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
| > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < | 104307 104308 104309 104310 104311 104312 104313 104314 104315 104316 104317 104318 104319 104320 104321 104322 104323 104324 104325 104326 104327 104328 104329 104330 104331 104332 104333 104334 104335 104336 104337 104338 104339 104340 104341 104342 104343 104344 104345 104346 104347 104348 104349 104350 104351 104352 104353 104354 104355 |
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */
Expr *pLimit; /* New limit expression */
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( ExprHasProperty(pExpr, EP_xIsSelect) );
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));
sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
return pExpr->iTable;
}
/* Begin coding the subroutine */
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"));
/* The evaluation of the EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
/* For a SELECT, generate code to put the values for all columns of
** the first row into an array of registers and return the index of
** the first register.
**
|
| ︙ | ︙ | |||
103765 103766 103767 103768 103769 103770 103771 103772 103773 103774 103775 103776 103777 |
}else{
/* If there is no pre-existing limit add a limit of 1 */
pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){
sqlite3VdbeJumpHere(v, addrOnce);
| > > > > | > | | | | < < | | 104390 104391 104392 104393 104394 104395 104396 104397 104398 104399 104400 104401 104402 104403 104404 104405 104406 104407 104408 104409 104410 104411 104412 104413 104414 104415 104416 104417 104418 104419 104420 104421 104422 104423 104424 104425 104426 104427 104428 104429 104430 104431 104432 104433 |
}else{
/* If there is no pre-existing limit add a limit of 1 */
pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
if( pParse->nErr ){
pExpr->op2 = pExpr->op;
pExpr->op = TK_ERROR;
}
return 0;
}
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);
if( (pIn->flags & EP_xIsSelect)!=0 && !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;
|
| ︙ | ︙ | |||
103982 103983 103984 103985 103986 103987 103988 103989 103990 103991 103992 103993 103994 103995 |
destStep2 = destIfFalse;
}else{
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
}
}
/* Step 3. The LHS is now known to be non-NULL. Do the binary search
| > | 104610 104611 104612 104613 104614 104615 104616 104617 104618 104619 104620 104621 104622 104623 104624 |
destStep2 = destIfFalse;
}else{
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
}
}
/* Step 3. The LHS is now known to be non-NULL. Do the binary search
|
| ︙ | ︙ | |||
104607 104608 104609 104610 104611 104612 104613 |
return target;
}
default: {
/* Make NULL the default case so that if a bug causes an illegal
** Expr node to be passed into this function, it will be handled
** sanely and not crash. But keep the assert() to bring the problem
** to the attention of the developers. */
| | | 105236 105237 105238 105239 105240 105241 105242 105243 105244 105245 105246 105247 105248 105249 105250 |
return target;
}
default: {
/* Make NULL the default case so that if a bug causes an illegal
** Expr node to be passed into this function, it will be handled
** sanely and not crash. But keep the assert() to bring the problem
** to the attention of the developers. */
assert( op==TK_NULL || op==TK_ERROR || pParse->db->mallocFailed );
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
int n;
const char *z;
|
| ︙ | ︙ | |||
104673 104674 104675 104676 104677 104678 104679 |
case TK_EQ: {
Expr *pLeft = pExpr->pLeft;
if( sqlite3ExprIsVector(pLeft) ){
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
| > | < > > > > > > | 105302 105303 105304 105305 105306 105307 105308 105309 105310 105311 105312 105313 105314 105315 105316 105317 105318 105319 105320 105321 105322 105323 105324 105325 105326 105327 105328 105329 105330 |
case TK_EQ: {
Expr *pLeft = pExpr->pLeft;
if( sqlite3ExprIsVector(pLeft) ){
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
sqlite3VdbeCurrentAddr(v)+2, p5,
ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
if( p5==SQLITE_NULLEQ ){
sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
}else{
sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
}
testcase( regFree1==0 );
testcase( regFree2==0 );
}
break;
}
case TK_AND:
case TK_OR:
|
| ︙ | ︙ | |||
104944 104945 104946 104947 104948 104949 104950 |
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
| | > | 105579 105580 105581 105582 105583 105584 105585 105586 105587 105588 105589 105590 105591 105592 105593 105594 |
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT
|| pExpr->pLeft->op==TK_ERROR );
if( pExpr->iTable!=0
&& pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
return pExpr->pLeft->iTable + pExpr->iColumn;
|
| ︙ | ︙ | |||
106424 106425 106426 106427 106428 106429 106430 |
assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
if( pExpr->op==TK_AGG_COLUMN ){
assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
| < | < | | 107060 107061 107062 107063 107064 107065 107066 107067 107068 107069 107070 107071 107072 107073 107074 107075 107076 107077 107078 107079 107080 107081 107082 107083 |
assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
if( pExpr->op==TK_AGG_COLUMN ){
assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
}
return WRC_Continue;
}
|
| ︙ | ︙ | |||
106578 106579 106580 106581 106582 106583 106584 106585 106586 106587 106588 106589 106590 106591 |
&& pWalker->walkerDepth==pExpr->op2
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
| > | 107212 107213 107214 107215 107216 107217 107218 107219 107220 107221 107222 107223 107224 107225 107226 |
&& pWalker->walkerDepth==pExpr->op2
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( pItem->pFExpr==pExpr ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
|
| ︙ | ︙ | |||
106778 106779 106780 106781 106782 106783 106784 106785 106786 106787 106788 106789 106790 106791 |
** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlite3ReadOnlyShadowTables(pParse->db)
)
#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
return 1;
| > | 107413 107414 107415 107416 107417 107418 107419 107420 107421 107422 107423 107424 107425 107426 107427 |
** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| (pTab->tabFlags & TF_Eponymous)!=0
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlite3ReadOnlyShadowTables(pParse->db)
)
#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
return 1;
|
| ︙ | ︙ | |||
106801 106802 106803 106804 106805 106806 106807 | ** objects unusable. */ static void renameTestSchema( Parse *pParse, /* Parse context */ const char *zDb, /* Name of db to verify schema of */ int bTemp, /* True if this is the temp db */ const char *zWhen, /* "when" part of error message */ | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > | 107437 107438 107439 107440 107441 107442 107443 107444 107445 107446 107447 107448 107449 107450 107451 107452 107453 107454 107455 107456 107457 107458 107459 107460 107461 107462 107463 107464 107465 107466 107467 107468 107469 107470 107471 107472 107473 107474 107475 107476 107477 107478 107479 107480 107481 107482 107483 107484 107485 107486 107487 107488 107489 107490 107491 107492 107493 107494 107495 |
** objects unusable.
*/
static void renameTestSchema(
Parse *pParse, /* Parse context */
const char *zDb, /* Name of db to verify schema of */
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\"." DFLT_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." DFLT_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\"." DFLT_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." DFLT_SCHEMA_TABLE
" SET sql = sqlite_rename_quotefix('temp', sql)"
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
);
}
}
/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
|
| ︙ | ︙ | |||
106984 106985 106986 106987 106988 106989 106990 |
** as required. */
if( iDb!=1 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_schema SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
| | | 107644 107645 107646 107647 107648 107649 107650 107651 107652 107653 107654 107655 107656 107657 107658 |
** as required. */
if( iDb!=1 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_schema SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
" sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
"THEN %Q ELSE tbl_name END "
"WHERE type IN ('view', 'trigger')"
, zDb, zTabName, zName, zTabName, zDb, zName);
}
/* If this is a virtual table, invoke the xRename() function if
** one is defined. The xRename() callback will modify the names
|
| ︙ | ︙ | |||
107342 107343 107344 107345 107346 107347 107348 107349 107350 107351 107352 107353 107354 107355 |
for(iCol=0; iCol<pTab->nCol; iCol++){
if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
}
if( iCol==pTab->nCol ){
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
goto exit_rename_column;
}
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_schema table.
*/
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
| > > > > | 108002 108003 108004 108005 108006 108007 108008 108009 108010 108011 108012 108013 108014 108015 108016 108017 108018 108019 |
for(iCol=0; iCol<pTab->nCol; iCol++){
if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
}
if( iCol==pTab->nCol ){
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
goto exit_rename_column;
}
/* Ensure the schema contains no double-quoted strings */
renameTestSchema(pParse, zDb, iSchema==1, "", 0);
renameFixQuotes(pParse, zDb, iSchema==1);
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_schema table.
*/
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
|
| ︙ | ︙ | |||
107372 107373 107374 107375 107376 107377 107378 |
"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);
| | | 108036 108037 108038 108039 108040 108041 108042 108043 108044 108045 108046 108047 108048 108049 108050 |
"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);
renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);
exit_rename_column:
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zOld);
sqlite3DbFree(db, zNew);
return;
}
|
| ︙ | ︙ | |||
107553 107554 107555 107556 107557 107558 107559 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
| | | 108217 108218 108219 108220 108221 108222 108223 108224 108225 108226 108227 108228 108229 108230 108231 |
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
if( p->selFlags & SF_View ) 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);
}
}
|
| ︙ | ︙ | |||
107637 107638 107639 107640 107641 107642 107643 |
*/
static RenameToken *renameTokenFind(
Parse *pParse,
struct RenameCtx *pCtx,
void *pPtr
){
RenameToken **pp;
| | > > | 108301 108302 108303 108304 108305 108306 108307 108308 108309 108310 108311 108312 108313 108314 108315 108316 108317 |
*/
static RenameToken *renameTokenFind(
Parse *pParse,
struct RenameCtx *pCtx,
void *pPtr
){
RenameToken **pp;
if( NEVER(pPtr==0) ){
return 0;
}
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
if( (*pp)->p==pPtr ){
RenameToken *pToken = *pp;
if( pCtx ){
*pp = pToken->pNext;
pToken->pNext = pCtx->pList;
pCtx->pList = pToken;
|
| ︙ | ︙ | |||
107796 107797 107798 107799 107800 107801 107802 | ** is initialized by this function before it is used. */ static int renameParseSql( Parse *p, /* Memory to use for Parse object */ const char *zDb, /* Name of schema SQL belongs to */ sqlite3 *db, /* Database handle */ const char *zSql, /* SQL to parse */ | | < < < < < | 108462 108463 108464 108465 108466 108467 108468 108469 108470 108471 108472 108473 108474 108475 108476 108477 108478 108479 108480 108481 |
** is initialized by this function before it is used.
*/
static int renameParseSql(
Parse *p, /* Memory to use for Parse object */
const char *zDb, /* Name of schema SQL belongs to */
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL to parse */
int bTemp /* True if SQL is from temp schema */
){
int rc;
char *zErr = 0;
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
** trigger object, the database must be corrupt. */
memset(p, 0, sizeof(Parse));
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
|
| ︙ | ︙ | |||
107839 107840 107841 107842 107843 107844 107845 |
for(pToken=p->pRename; pToken; pToken=pToken->pNext){
assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
}
}
#endif
db->init.iDb = 0;
| < | 108500 108501 108502 108503 108504 108505 108506 108507 108508 108509 108510 108511 108512 108513 |
for(pToken=p->pRename; pToken; pToken=pToken->pNext){
assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
}
}
#endif
db->init.iDb = 0;
return rc;
}
/*
** This function edits SQL statement zSql, replacing each token identified
** by the linked list pRename with the text of zNew. If argument bQuote is
** true, then zNew is always quoted first. If no error occurs, the result
|
| ︙ | ︙ | |||
107863 107864 107865 107866 107867 107868 107869 |
const char *zNew, /* New token text */
int bQuote /* True to always quote token */
){
int nNew = sqlite3Strlen30(zNew);
int nSql = sqlite3Strlen30(zSql);
sqlite3 *db = sqlite3_context_db_handle(pCtx);
int rc = SQLITE_OK;
| | | > > > | | | | | | | | | | | | | > > > > | > | | > | | < < < < > > > | | | | | | > > > > > > > > > > > > > > > > > | 108523 108524 108525 108526 108527 108528 108529 108530 108531 108532 108533 108534 108535 108536 108537 108538 108539 108540 108541 108542 108543 108544 108545 108546 108547 108548 108549 108550 108551 108552 108553 108554 108555 108556 108557 108558 108559 108560 108561 108562 108563 108564 108565 108566 108567 108568 108569 108570 108571 108572 108573 108574 108575 108576 108577 108578 108579 108580 108581 108582 108583 108584 108585 108586 108587 108588 108589 108590 108591 108592 108593 108594 108595 108596 108597 108598 108599 108600 108601 108602 |
const char *zNew, /* New token text */
int bQuote /* True to always quote token */
){
int nNew = sqlite3Strlen30(zNew);
int nSql = sqlite3Strlen30(zSql);
sqlite3 *db = sqlite3_context_db_handle(pCtx);
int rc = SQLITE_OK;
char *zQuot = 0;
char *zOut;
int nQuot = 0;
char *zBuf1 = 0;
char *zBuf2 = 0;
if( zNew ){
/* Set zQuot to point to a buffer containing a quoted copy of the
** identifier zNew. If the corresponding identifier in the original
** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
** point to zQuot so that all substitutions are made using the
** quoted version of the new column name. */
zQuot = sqlite3MPrintf(db, "\"%w\" ", zNew);
if( zQuot==0 ){
return SQLITE_NOMEM;
}else{
nQuot = sqlite3Strlen30(zQuot)-1;
}
assert( nQuot>=nNew );
zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
}else{
zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
}
}
/* At this point pRename->pList contains a list of RenameToken objects
** corresponding to all tokens in the input SQL that must be replaced
** with the new column name, or with single-quoted versions of themselves.
** All that remains is to construct and return the edited SQL string. */
if( zOut ){
int nOut = nSql;
memcpy(zOut, zSql, nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
u32 nReplace;
const char *zReplace;
RenameToken *pBest = renameColumnTokenNext(pRename);
if( zNew ){
if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
nReplace = nNew;
zReplace = zNew;
}else{
nReplace = nQuot;
zReplace = zQuot;
if( pBest->t.z[pBest->t.n]=='"' ) nReplace++;
}
}else{
/* Dequote the double-quoted token. Then requote it again, this time
** using single quotes. If the character immediately following the
** original token within the input SQL was a single quote ('), then
** add another space after the new, single-quoted version of the
** token. This is so that (SELECT "string"'alias') maps to
** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
memcpy(zBuf1, pBest->t.z, pBest->t.n);
zBuf1[pBest->t.n] = 0;
sqlite3Dequote(zBuf1);
sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
pBest->t.z[pBest->t.n]=='\'' ? " " : ""
);
zReplace = zBuf2;
nReplace = sqlite3Strlen30(zReplace);
}
iOff = pBest->t.z - zSql;
if( pBest->t.n!=nReplace ){
memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n],
nOut - (iOff + pBest->t.n)
);
|
| ︙ | ︙ | |||
108141 108142 108143 108144 108145 108146 108147 | zOld = pTab->aCol[iCol].zName; memset(&sCtx, 0, sizeof(sCtx)); sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = 0; #endif | | | 108826 108827 108828 108829 108830 108831 108832 108833 108834 108835 108836 108837 108838 108839 108840 | zOld = pTab->aCol[iCol].zName; memset(&sCtx, 0, sizeof(sCtx)); sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol); #ifndef SQLITE_OMIT_AUTHORIZATION db->xAuth = 0; #endif rc = renameParseSql(&sParse, zDb, db, zSql, bTemp); /* Find tokens that need to be replaced. */ memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = &sParse; sWalker.xExprCallback = renameColumnExprCb; sWalker.xSelectCallback = renameColumnSelectCb; sWalker.u.pRename = &sCtx; |
| ︙ | ︙ | |||
108170 108171 108172 108173 108174 108175 108176 |
}else{
/* A regular table */
int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
FKey *pFKey;
assert( sParse.pNewTable->pSelect==0 );
sCtx.pTab = sParse.pNewTable;
if( bFKOnly==0 ){
| > | | | > | 108855 108856 108857 108858 108859 108860 108861 108862 108863 108864 108865 108866 108867 108868 108869 108870 108871 108872 108873 |
}else{
/* A regular table */
int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
FKey *pFKey;
assert( sParse.pNewTable->pSelect==0 );
sCtx.pTab = sParse.pNewTable;
if( bFKOnly==0 ){
if( iCol<sParse.pNewTable->nCol ){
renameTokenFind(
&sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
);
}
if( sCtx.iCol<0 ){
renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
}
sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
|
| ︙ | ︙ | |||
108275 108276 108277 108278 108279 108280 108281 |
** Walker select callback used by "RENAME TABLE".
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSelect->selFlags & SF_View ) return WRC_Prune;
| | | 108962 108963 108964 108965 108966 108967 108968 108969 108970 108971 108972 108973 108974 108975 108976 |
** Walker select callback used by "RENAME TABLE".
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSelect->selFlags & SF_View ) return WRC_Prune;
if( NEVER(pSrc==0) ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
for(i=0; i<pSrc->nSrc; i++){
SrcItem *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
|
| ︙ | ︙ | |||
108345 108346 108347 108348 108349 108350 108351 |
sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = &sParse;
sWalker.xExprCallback = renameTableExprCb;
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
| | | 109032 109033 109034 109035 109036 109037 109038 109039 109040 109041 109042 109043 109044 109045 109046 |
sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = &sParse;
sWalker.xExprCallback = renameTableExprCb;
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
if( sParse.pNewTable ){
Table *pTab = sParse.pNewTable;
if( pTab->pSelect ){
|
| ︙ | ︙ | |||
108447 108448 108449 108450 108451 108452 108453 108454 108455 108456 108457 108458 108459 108460 108461 108462 108463 108464 108465 108466 108467 |
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
}
return;
}
/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it is still usable.
**
** 0: Database name ("main", "temp" etc.).
** 1: SQL statement.
** 2: Object type ("view", "table", "trigger" or "index").
** 3: Object name.
** 4: True if object is from temp schema.
** 5: "when" part of error message.
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > | > | 109134 109135 109136 109137 109138 109139 109140 109141 109142 109143 109144 109145 109146 109147 109148 109149 109150 109151 109152 109153 109154 109155 109156 109157 109158 109159 109160 109161 109162 109163 109164 109165 109166 109167 109168 109169 109170 109171 109172 109173 109174 109175 109176 109177 109178 109179 109180 109181 109182 109183 109184 109185 109186 109187 109188 109189 109190 109191 109192 109193 109194 109195 109196 109197 109198 109199 109200 109201 109202 109203 109204 109205 109206 109207 109208 109209 109210 109211 109212 109213 109214 109215 109216 109217 109218 109219 109220 109221 109222 109223 109224 109225 109226 109227 109228 109229 109230 109231 109232 109233 109234 109235 109236 109237 109238 109239 109240 109241 109242 109243 109244 109245 109246 109247 109248 109249 109250 109251 109252 109253 109254 109255 109256 109257 109258 109259 109260 109261 109262 109263 109264 109265 109266 109267 109268 109269 109270 109271 109272 109273 109274 109275 109276 109277 109278 109279 109280 109281 109282 109283 109284 109285 109286 109287 109288 109289 109290 109291 109292 109293 109294 109295 109296 109297 109298 109299 109300 109301 109302 109303 109304 109305 109306 109307 109308 109309 |
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
}
return;
}
static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
renameTokenFind(pWalker->pParse, pWalker->u.pRename, (void*)pExpr);
}
return WRC_Continue;
}
/*
** The implementation of an SQL scalar function that rewrites DDL statements
** so that any string literals that use double-quotes are modified so that
** they use single quotes.
**
** Two arguments must be passed:
**
** 0: Database name ("main", "temp" etc.).
** 1: SQL statement to edit.
**
** The returned value is the modified SQL statement. For example, given
** the database schema:
**
** CREATE TABLE t1(a, b, c);
**
** SELECT sqlite_rename_quotefix('main',
** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
** );
**
** returns the string:
**
** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
*/
static void renameQuotefixFunc(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
db->xAuth = 0;
#endif
sqlite3BtreeEnterAll(db);
UNUSED_PARAMETER(NotUsed);
if( zDb && zInput ){
int rc;
Parse sParse;
rc = renameParseSql(&sParse, zDb, db, zInput, 0);
if( rc==SQLITE_OK ){
RenameCtx sCtx;
Walker sWalker;
/* Walker to find tokens that need to be replaced. */
memset(&sCtx, 0, sizeof(RenameCtx));
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = &sParse;
sWalker.xExprCallback = renameQuotefixExprCb;
sWalker.xSelectCallback = renameColumnSelectCb;
sWalker.u.pRename = &sCtx;
if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect;
if( pSelect ){
pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
if( rc==SQLITE_OK ){
sqlite3WalkSelect(&sWalker, pSelect);
}
}else{
int i;
sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
for(i=0; i<sParse.pNewTable->nCol; i++){
sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
}
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
}
}else if( sParse.pNewIndex ){
sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
}else{
#ifndef SQLITE_OMIT_TRIGGER
rc = renameResolveTrigger(&sParse);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, sParse.pNewTrigger);
}
#endif /* SQLITE_OMIT_TRIGGER */
}
if( rc==SQLITE_OK ){
rc = renameEditSql(context, &sCtx, zInput, 0, 0);
}
renameTokenFree(db, sCtx.pList);
}
if( rc!=SQLITE_OK ){
sqlite3_result_error_code(context, rc);
}
renameParseCleanup(&sParse);
}
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
#endif
sqlite3BtreeLeaveAll(db);
}
/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it is still usable.
**
** 0: Database name ("main", "temp" etc.).
** 1: SQL statement.
** 2: Object type ("view", "table", "trigger" or "index").
** 3: Object name.
** 4: True if object is from temp schema.
** 5: "when" part of error message.
** 6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
**
** * the SQL argument creates a trigger, and
** * the table that the trigger is attached to is in database zDb.
*/
static void renameTableTest(
sqlite3_context *context,
int NotUsed,
sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
char const *zDb = (const char*)sqlite3_value_text(argv[0]);
char const *zInput = (const char*)sqlite3_value_text(argv[1]);
int bTemp = sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
int bNoDQS = sqlite3_value_int(argv[6]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
db->xAuth = 0;
#endif
UNUSED_PARAMETER(NotUsed);
if( zDb && zInput ){
int rc;
Parse sParse;
int flags = db->flags;
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
|
| ︙ | ︙ | |||
108559 108560 108561 108562 108563 108564 108565 | #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif UNUSED_PARAMETER(NotUsed); | | | 109363 109364 109365 109366 109367 109368 109369 109370 109371 109372 109373 109374 109375 109376 109377 |
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth = db->xAuth;
db->xAuth = 0;
#endif
UNUSED_PARAMETER(NotUsed);
rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
if( rc!=SQLITE_OK ) goto drop_column_done;
pTab = sParse.pNewTable;
if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
/* This can happen if the sqlite_schema table is corrupt */
rc = SQLITE_CORRUPT_BKPT;
goto drop_column_done;
}
|
| ︙ | ︙ | |||
108653 108654 108655 108656 108657 108658 108659 108660 108661 108662 108663 108664 108665 108666 108667 108668 |
}
/* Edit the sqlite_schema table */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 );
zDb = db->aDb[iDb].zDbSName;
renameTestSchema(pParse, zDb, iDb==1, "", 0);
sqlite3NestedParse(pParse,
"UPDATE \"%w\"." DFLT_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);
| > | < > > > > | > > > > > > > | > < > > | 109457 109458 109459 109460 109461 109462 109463 109464 109465 109466 109467 109468 109469 109470 109471 109472 109473 109474 109475 109476 109477 109478 109479 109480 109481 109482 109483 109484 109485 109486 109487 109488 109489 109490 109491 109492 109493 109494 109495 109496 109497 109498 109499 109500 109501 109502 109503 109504 109505 109506 109507 109508 109509 109510 109511 109512 109513 109514 109515 109516 109517 109518 109519 109520 109521 109522 109523 109524 109525 109526 109527 109528 109529 109530 109531 109532 109533 109534 109535 109536 109537 109538 109539 109540 109541 109542 109543 109544 109545 109546 109547 109548 109549 109550 109551 109552 109553 109554 |
}
/* 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\"." DFLT_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);
renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);
/* Edit rows of table on disk */
if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
int i;
int addr;
int reg;
int regRec;
Index *pPk = 0;
int nField = 0; /* Number of non-virtual columns after drop */
int iCur;
Vdbe *v = sqlite3GetVdbe(pParse);
iCur = pParse->nTab++;
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
reg = ++pParse->nMem;
if( HasRowid(pTab) ){
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
pParse->nMem += pTab->nCol;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem += pPk->nColumn;
for(i=0; i<pPk->nKeyCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
}
nField = pPk->nKeyCol;
}
regRec = ++pParse->nMem;
for(i=0; i<pTab->nCol; i++){
if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
int regOut;
if( pPk ){
int iPos = sqlite3TableColumnToIndex(pPk, i);
int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
if( iPos<pPk->nKeyCol ) continue;
regOut = reg+1+iPos-(iPos>iColPos);
}else{
regOut = reg+1+nField;
}
if( i==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
}else{
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
}
nField++;
}
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
if( pPk ){
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
}else{
sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
}
sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr);
}
exit_drop_column:
sqlite3DbFree(db, zCol);
sqlite3SrcListDelete(db, pSrc);
}
/*
** Register built-in functions used to help implement ALTER TABLE
*/
SQLITE_PRIVATE void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif /* SQLITE_ALTER_TABLE */
/************** End of alter.c ***********************************************/
/************** Begin file analyze.c *****************************************/
|
| ︙ | ︙ | |||
110774 110775 110776 110777 110778 110779 110780 | UNUSED_PARAMETER(NotUsed); zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; | | | 111591 111592 111593 111594 111595 111596 111597 111598 111599 111600 111601 111602 111603 111604 111605 |
UNUSED_PARAMETER(NotUsed);
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db) (0)
#endif
if( REOPEN_AS_MEMDB(db) ){
/* This is not a real ATTACH. Instead, this routine is being called
|
| ︙ | ︙ | |||
111143 111144 111145 111146 111147 111148 111149 |
sqlite3 *db = pFix->pParse->db;
int iDb = sqlite3FindDbName(db, pFix->zDb);
SrcList *pList = pSelect->pSrc;
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pFix->bTemp==0 ){
| > | | | | | | | | > > | 111960 111961 111962 111963 111964 111965 111966 111967 111968 111969 111970 111971 111972 111973 111974 111975 111976 111977 111978 111979 111980 111981 111982 111983 111984 |
sqlite3 *db = pFix->pParse->db;
int iDb = sqlite3FindDbName(db, pFix->zDb);
SrcList *pList = pSelect->pSrc;
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pFix->bTemp==0 ){
if( pItem->zDatabase ){
if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return WRC_Abort;
}
sqlite3DbFree(db, pItem->zDatabase);
pItem->zDatabase = 0;
pItem->fg.notCte = 1;
}
pItem->pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
#endif
}
|
| ︙ | ︙ | |||
111190 111191 111192 111193 111194 111195 111196 | pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; pFix->bTemp = (iDb==1); pFix->w.pParse = pParse; pFix->w.xExprCallback = fixExprCb; pFix->w.xSelectCallback = fixSelectCb; | | | 112010 112011 112012 112013 112014 112015 112016 112017 112018 112019 112020 112021 112022 112023 112024 | pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; pFix->bTemp = (iDb==1); pFix->w.pParse = pParse; pFix->w.xExprCallback = fixExprCb; pFix->w.xSelectCallback = fixSelectCb; pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback; pFix->w.walkerDepth = 0; pFix->w.eCode = 0; pFix->w.u.pFix = pFix; } /* ** The following set of routines walk through the parse tree and assign |
| ︙ | ︙ | |||
111252 111253 111254 111255 111256 111257 111258 |
|| sqlite3WalkExpr(&pFix->w, pStep->pWhere)
|| sqlite3WalkExprList(&pFix->w, pStep->pExprList)
|| sqlite3FixSrcList(pFix, pStep->pFrom)
){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
| < > | > | | | | | | > | 112072 112073 112074 112075 112076 112077 112078 112079 112080 112081 112082 112083 112084 112085 112086 112087 112088 112089 112090 112091 112092 112093 112094 112095 |
|| sqlite3WalkExpr(&pFix->w, pStep->pWhere)
|| sqlite3WalkExprList(&pFix->w, pStep->pExprList)
|| sqlite3FixSrcList(pFix, pStep->pFrom)
){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
{
Upsert *pUp;
for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
|| sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
|| sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
){
return 1;
}
}
}
#endif
pStep = pStep->pNext;
}
return 0;
|
| ︙ | ︙ | |||
111591 111592 111593 111594 111595 111596 111597 | ** The table to be locked has root page iTab and is found in database iDb. ** A read or a write lock can be taken depending on isWritelock. ** ** This routine just records the fact that the lock is desired. The ** code to make the lock occur is generated by a later call to ** codeTableLocks() which occurs during sqlite3FinishCoding(). */ | | < < | 112413 112414 112415 112416 112417 112418 112419 112420 112421 112422 112423 112424 112425 112426 112427 112428 112429 112430 112431 112432 112433 112434 112435 112436 112437 112438 112439 |
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
**
** This routine just records the fact that the lock is desired. The
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
static SQLITE_NOINLINE void lockTable(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
Parse *pToplevel;
int i;
int nBytes;
TableLock *p;
assert( iDb>=0 );
pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
p->isWriteLock = (p->isWriteLock || isWriteLock);
return;
}
|
| ︙ | ︙ | |||
111629 111630 111631 111632 111633 111634 111635 111636 111637 111638 111639 111640 111641 111642 |
p->isWriteLock = isWriteLock;
p->zLockName = zName;
}else{
pToplevel->nTableLock = 0;
sqlite3OomFault(pToplevel->db);
}
}
/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
int i;
| > > > > > > > > > > > | 112449 112450 112451 112452 112453 112454 112455 112456 112457 112458 112459 112460 112461 112462 112463 112464 112465 112466 112467 112468 112469 112470 112471 112472 112473 |
p->isWriteLock = isWriteLock;
p->zLockName = zName;
}else{
pToplevel->nTableLock = 0;
sqlite3OomFault(pToplevel->db);
}
}
SQLITE_PRIVATE void sqlite3TableLock(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
lockTable(pParse, iDb, iTab, isWriteLock, zName);
}
/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
int i;
|
| ︙ | ︙ | |||
111983 111984 111985 111986 111987 111988 111989 |
p = sqlite3FindTable(db, zName, zDbase);
if( p==0 ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
| | | 112814 112815 112816 112817 112818 112819 112820 112821 112822 112823 112824 112825 112826 112827 112828 |
p = sqlite3FindTable(db, zName, zDbase);
if( p==0 ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
if( pParse->disableVtab==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
|
| ︙ | ︙ | |||
112006 112007 112008 112009 112010 112011 112012 112013 112014 112015 112016 112017 112018 112019 |
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
if( zDbase ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
}
return p;
}
/*
** Locate the table identified by *p.
| > > | 112837 112838 112839 112840 112841 112842 112843 112844 112845 112846 112847 112848 112849 112850 112851 112852 |
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
if( zDbase ){
sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
}else{
sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
}else{
assert( HasRowid(p) || p->iPKey<0 );
}
return p;
}
/*
** Locate the table identified by *p.
|
| ︙ | ︙ | |||
112422 112423 112424 112425 112426 112427 112428 |
*pUnqual = pName2;
iDb = sqlite3FindDb(db, pName1);
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
return -1;
}
}else{
| | | 113255 113256 113257 113258 113259 113260 113261 113262 113263 113264 113265 113266 113267 113268 113269 |
*pUnqual = pName2;
iDb = sqlite3FindDb(db, pName1);
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
return -1;
}
}else{
assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE
|| (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
}
return iDb;
}
|
| ︙ | ︙ | |||
112590 112591 112592 112593 112594 112595 112596 112597 112598 112599 112600 112601 112602 112603 |
return pTab->nNVCol + i - n;
}else{
/* iCol is a normal or stored column */
return n;
}
}
#endif
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement. In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
** flag is true if the table should be stored in the auxiliary database
| > > > > > > > > > > > > > > > > > | 113423 113424 113425 113426 113427 113428 113429 113430 113431 113432 113433 113434 113435 113436 113437 113438 113439 113440 113441 113442 113443 113444 113445 113446 113447 113448 113449 113450 113451 113452 113453 |
return pTab->nNVCol + i - n;
}else{
/* iCol is a normal or stored column */
return n;
}
}
#endif
/*
** Insert a single OP_JournalMode query opcode in order to force the
** prepared statement to return false for sqlite3_stmt_readonly(). This
** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
** will return false for sqlite3_stmt_readonly() even if that statement
** is a read-only no-op.
*/
static void sqlite3ForceNotReadOnly(Parse *pParse){
int iReg = ++pParse->nMem;
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
sqlite3VdbeUsesBtree(v, 0);
}
}
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement. In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
** flag is true if the table should be stored in the auxiliary database
|
| ︙ | ︙ | |||
112690 112691 112692 112693 112694 112695 112696 112697 112698 112699 112700 112701 112702 112703 |
pTable = sqlite3FindTable(db, zName, zDb);
if( pTable ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto begin_table_error;
}
if( sqlite3FindIndex(db, zName, zDb)!=0 ){
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
goto begin_table_error;
}
| > | 113540 113541 113542 113543 113544 113545 113546 113547 113548 113549 113550 113551 113552 113553 113554 |
pTable = sqlite3FindTable(db, zName, zDb);
if( pTable ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
if( sqlite3FindIndex(db, zName, zDb)!=0 ){
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
goto begin_table_error;
}
|
| ︙ | ︙ | |||
112718 112719 112720 112721 112722 112723 112724 | pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST); #else pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #endif assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; | < < < < < < < < < < < | 113569 113570 113571 113572 113573 113574 113575 113576 113577 113578 113579 113580 113581 113582 | pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST); #else pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #endif assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; /* Begin generating the code that will insert the table record into ** the schema table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** indices. Hence, the record number for the table must be allocated ** now. |
| ︙ | ︙ | |||
112877 112878 112879 112880 112881 112882 112883 112884 112885 112886 112887 112888 112889 112890 | testcase( pParse->earlyCleanup ); if( db->mallocFailed ) return; pRet->retTrig.zName = RETURNING_TRIGGER_NAME; pRet->retTrig.op = TK_RETURNING; pRet->retTrig.tr_tm = TRIGGER_AFTER; pRet->retTrig.bReturning = 1; pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.step_list = &pRet->retTStep; pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr ); if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) | > | 113717 113718 113719 113720 113721 113722 113723 113724 113725 113726 113727 113728 113729 113730 113731 | testcase( pParse->earlyCleanup ); if( db->mallocFailed ) return; pRet->retTrig.zName = RETURNING_TRIGGER_NAME; pRet->retTrig.op = TK_RETURNING; pRet->retTrig.tr_tm = TRIGGER_AFTER; pRet->retTrig.bReturning = 1; pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.pTabSchema = db->aDb[1].pSchema; pRet->retTrig.step_list = &pRet->retTStep; pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr ); if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) |
| ︙ | ︙ | |||
113735 113736 113737 113738 113739 113740 113741 |
*/
if( pTab->iPKey>=0 ){
ExprList *pList;
Token ipkToken;
sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
| | > > > | > > > | 114576 114577 114578 114579 114580 114581 114582 114583 114584 114585 114586 114587 114588 114589 114590 114591 114592 114593 114594 114595 114596 114597 114598 114599 114600 114601 114602 114603 114604 114605 |
*/
if( pTab->iPKey>=0 ){
ExprList *pList;
Token ipkToken;
sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
pList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
if( pList==0 ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
pList->a[0].sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( db->mallocFailed || pParse->nErr ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
/*
|
| ︙ | ︙ | |||
113948 113949 113950 113951 113952 113953 113954 |
sqlite3 *db = pParse->db; /* The database connection */
int iDb; /* Database in which the table lives */
Index *pIdx; /* An implied index of the table */
if( pEnd==0 && pSelect==0 ){
return;
}
| < | 114795 114796 114797 114798 114799 114800 114801 114802 114803 114804 114805 114806 114807 114808 |
sqlite3 *db = pParse->db; /* The database connection */
int iDb; /* Database in which the table lives */
Index *pIdx; /* An implied index of the table */
if( pEnd==0 && pSelect==0 ){
return;
}
p = pParse->pNewTable;
if( p==0 ) return;
if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
p->tabFlags |= TF_Shadow;
}
|
| ︙ | ︙ | |||
114173 114174 114175 114176 114177 114178 114179 |
sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
| | | 115019 115020 115021 115022 115023 115024 115025 115026 115027 115028 115029 115030 115031 115032 115033 |
sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){
Db *pDb = &db->aDb[iDb];
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->pSeqTab==0 ){
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_sequence(name,seq)",
pDb->zDbSName
);
|
| ︙ | ︙ | |||
114196 114197 114198 114199 114200 114201 114202 114203 114204 114205 114206 114207 114208 114209 114210 114211 114212 114213 114214 114215 114216 114217 |
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy ){
Table *pOld;
Schema *pSchema = p->pSchema;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
sqlite3OomFault(db);
return;
}
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
}
#ifndef SQLITE_OMIT_ALTERTABLE
if( !pSelect && !p->pSelect ){
assert( pCons && pEnd );
if( pCons->z==0 ){
pCons = pEnd;
| > > > > > > > > > > > > | 115042 115043 115044 115045 115046 115047 115048 115049 115050 115051 115052 115053 115054 115055 115056 115057 115058 115059 115060 115061 115062 115063 115064 115065 115066 115067 115068 115069 115070 115071 115072 115073 115074 115075 |
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy ){
Table *pOld;
Schema *pSchema = p->pSchema;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
assert( HasRowid(p) || p->iPKey<0 );
pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
sqlite3OomFault(db);
return;
}
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
/* If this is the magic sqlite_sequence table used by autoincrement,
** then record a pointer to this table in the main database structure
** so that INSERT can find the table easily. */
assert( !pParse->nested );
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( strcmp(p->zName, "sqlite_sequence")==0 ){
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
p->pSchema->pSeqTab = p;
}
#endif
}
#ifndef SQLITE_OMIT_ALTERTABLE
if( !pSelect && !p->pSelect ){
assert( pCons && pEnd );
if( pCons->z==0 ){
pCons = pEnd;
|
| ︙ | ︙ | |||
114247 114248 114249 114250 114251 114252 114253 114254 114255 114256 114257 114258 114259 114260 |
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
goto create_view_fail;
}
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ) goto create_view_fail;
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
/* Make a copy of the entire SELECT statement that defines the view.
** This will force all the Expr.token.z values to be dynamically
| > > > > > > > > > > | 115105 115106 115107 115108 115109 115110 115111 115112 115113 115114 115115 115116 115117 115118 115119 115120 115121 115122 115123 115124 115125 115126 115127 115128 |
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
goto create_view_fail;
}
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ) goto create_view_fail;
/* Legacy versions of SQLite allowed the use of the magic "rowid" column
** on a view, even though views do not have rowids. The following flag
** setting fixes this problem. But the fix can be disabled by compiling
** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
** depend upon the old buggy behavior. */
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
p->tabFlags |= TF_NoVisibleRowid;
#endif
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;
/* Make a copy of the entire SELECT statement that defines the view.
** This will force all the Expr.token.z values to be dynamically
|
| ︙ | ︙ | |||
114723 114724 114725 114726 114727 114728 114729 |
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
| > | > > | 115591 115592 115593 115594 115595 115596 115597 115598 115599 115600 115601 115602 115603 115604 115605 115606 115607 115608 |
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
if( noErr ){
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
goto exit_drop_table;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<db->nDb );
/* If pTab is a virtual table, call ViewGetColumnNames() to ensure
** it is initialized.
|
| ︙ | ︙ | |||
115293 115294 115295 115296 115297 115298 115299 115300 115301 115302 115303 115304 115305 115306 |
}
if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto exit_create_index;
}
}
}else{
int n;
Index *pLoop;
| > | 116164 116165 116166 116167 116168 116169 116170 116171 116172 116173 116174 116175 116176 116177 116178 |
}
if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
}
}else{
int n;
Index *pLoop;
|
| ︙ | ︙ | |||
115773 115774 115775 115776 115777 115778 115779 |
** stat1 data to be ignored by the query planner.
*/
x = pIdx->pTable->nRowLogEst;
assert( 99==sqlite3LogEst(1000) );
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
| | | 116645 116646 116647 116648 116649 116650 116651 116652 116653 116654 116655 116656 116657 116658 116659 |
** stat1 data to be ignored by the query planner.
*/
x = pIdx->pTable->nRowLogEst;
assert( 99==sqlite3LogEst(1000) );
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlite3LogEst(2) ); }
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
a[i] = 23; assert( 23==sqlite3LogEst(5) );
|
| ︙ | ︙ | |||
115808 115809 115810 115811 115812 115813 115814 |
assert( pName->nSrc==1 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
if( !ifExists ){
| | > | 116680 116681 116682 116683 116684 116685 116686 116687 116688 116689 116690 116691 116692 116693 116694 116695 116696 116697 |
assert( pName->nSrc==1 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
}
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
"or PRIMARY KEY constraint cannot be dropped", 0);
|
| ︙ | ︙ | |||
116122 116123 116124 116125 116126 116127 116128 |
/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
SrcItem *pItem;
| | | | 116995 116996 116997 116998 116999 117000 117001 117002 117003 117004 117005 117006 117007 117008 117009 117010 |
/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
SrcItem *pItem;
assert( pList || pParse->db->mallocFailed );
if( ALWAYS(pList) ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
if( pItem->pSelect ){
sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
}
}
|
| ︙ | ︙ | |||
117848 117849 117850 117851 117852 117853 117854 117855 117856 117857 117858 117859 117860 117861 |
if( HasRowid(pTab) ){
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1,
pTab->zName, P4_STATIC);
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
| > > > | 118721 118722 118723 118724 118725 118726 118727 118728 118729 118730 118731 118732 118733 118734 118735 118736 118737 |
if( HasRowid(pTab) ){
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt ? memCnt : -1,
pTab->zName, P4_STATIC);
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
sqlite3VdbeChangeP3(v, -1, memCnt ? memCnt : -1);
}
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
|
| ︙ | ︙ | |||
120460 120461 120462 120463 120464 120465 120466 | v1 = sqlite3_value_double(argv[1]); x = (double(*)(double,double))sqlite3_user_data(context); ans = x(v0, v1); sqlite3_result_double(context, ans); } /* | | < < | 121336 121337 121338 121339 121340 121341 121342 121343 121344 121345 121346 121347 121348 121349 121350 |
v1 = sqlite3_value_double(argv[1]);
x = (double(*)(double,double))sqlite3_user_data(context);
ans = x(v0, v1);
sqlite3_result_double(context, ans);
}
/*
** Implementation of 0-argument pi() function.
*/
static void piFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==0 );
|
| ︙ | ︙ | |||
122492 122493 122494 122495 122496 122497 122498 |
Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
/* Verify that the sqlite_sequence table exists and is an ordinary
** rowid table with exactly two columns.
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
| | | 123366 123367 123368 123369 123370 123371 123372 123373 123374 123375 123376 123377 123378 123379 123380 |
Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
/* Verify that the sqlite_sequence table exists and is an ordinary
** rowid table with exactly two columns.
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
|| NEVER(IsVirtual(pSeqTab))
|| pSeqTab->nCol!=2
){
pParse->nErr++;
pParse->rc = SQLITE_CORRUPT_SEQUENCE;
return 0;
}
|
| ︙ | ︙ | |||
122951 122952 122953 122954 122955 122956 122957 |
}
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
| | | 123825 123826 123827 123828 123829 123830 123831 123832 123833 123834 123835 123836 123837 123838 123839 |
}
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
pTabList->a, pColumn->a[i].zName);
pParse->checkSchema = 1;
goto insert_cleanup;
}
}
}
}
|
| ︙ | ︙ | |||
123079 123080 123081 123082 123083 123084 123085 |
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
}
}
if( nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
| | | 123953 123954 123955 123956 123957 123958 123959 123960 123961 123962 123963 123964 123965 123966 123967 |
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
}
}
if( nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
pTabList->a, pTab->nCol-nHidden, nColumn);
goto insert_cleanup;
}
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
goto insert_cleanup;
}
|
| ︙ | ︙ | |||
123382 123383 123384 123385 123386 123387 123388 |
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
sqlite3MayAbort(pParse);
}else
#endif
{
| | > > > > > > > | 124256 124257 124258 124259 124260 124261 124262 124263 124264 124265 124266 124267 124268 124269 124270 124271 124272 124273 124274 124275 124276 124277 124278 124279 124280 124281 124282 124283 124284 124285 124286 124287 124288 124289 124290 124291 124292 124293 124294 124295 124296 |
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
sqlite3MayAbort(pParse);
}else
#endif
{
int isReplace = 0;/* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
);
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
/* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
** constraints or (b) there are no triggers and this table is not a
** parent table in a foreign key constraint. It is safe to set the
** flag in the second case as if any REPLACE constraint is hit, an
** OP_Delete or OP_IdxDelete instruction will be executed on each
** cursor that is disturbed. And these instructions both clear the
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
** functionality. */
bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
}else if( pParse->bReturning ){
/* If there is a RETURNING clause, populate the rowid register with
** constant value -1, in case one or more of the returned expressions
** refer to the "rowid" of the view. */
sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
#endif
}
/* Update the count of rows that are inserted
*/
if( regRowCount ){
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
|
| ︙ | ︙ | |||
130204 130205 130206 130207 130208 130209 130210 130211 130212 130213 130214 130215 130216 130217 |
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( argc==5 );
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
db->mDbFlags |= DBFLAG_EncodingFixed;
pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv, 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
| > < | 131085 131086 131087 131088 131089 131090 131091 131092 131093 131094 131095 131096 131097 131098 131099 131100 131101 131102 131103 131104 131105 131106 |
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( argc==5 );
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
db->mDbFlags |= DBFLAG_EncodingFixed;
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv, 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv[3]==0 ){
corruptSchema(pData, argv, 0);
}else if( argv[4]
&& 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
&& 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
|
| ︙ | ︙ | |||
130488 130489 130490 130491 130492 130493 130494 |
sqlite3AnalysisLoad(db, iDb);
}
#endif
}
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
| | | | | | | > > | | | 131369 131370 131371 131372 131373 131374 131375 131376 131377 131378 131379 131380 131381 131382 131383 131384 131385 131386 131387 131388 131389 131390 131391 131392 131393 |
sqlite3AnalysisLoad(db, iDb);
}
#endif
}
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}else
if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
/* Hack: If the SQLITE_NoSchemaError flag is set, then consider
** the schema loaded, even if errors (other than OOM) occurred. In
** this situation the current sqlite3_prepare() operation will fail,
** but the following one will attempt to compile the supplied statement
** against whatever subset of the schema was loaded before the error
** occurred.
**
** The primary purpose of this is to allow access to the sqlite_schema
** table even when its contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
}
/* Jump here for an error that occurs after successfully allocating
** curMain and calling sqlite3BtreeEnter(). For an error that occurs
|
| ︙ | ︙ | |||
130606 130607 130608 130609 130610 130611 130612 130613 130614 130615 130616 130617 130618 130619 |
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
}
/* Read the schema cookie from the database. If it does not match the
** value stored as part of the in-memory schema representation,
| > | 131489 131490 131491 131492 131493 131494 131495 131496 131497 131498 131499 131500 131501 131502 131503 |
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
pParse->rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
}
/* Read the schema cookie from the database. If it does not match the
** value stored as part of the in-memory schema representation,
|
| ︙ | ︙ | |||
130841 130842 130843 130844 130845 130846 130847 130848 130849 130850 130851 130852 130853 130854 |
}
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
}
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( sParse.pVdbe ){
sqlite3VdbeFinalize(sParse.pVdbe);
| > | 131725 131726 131727 131728 131729 131730 131731 131732 131733 131734 131735 131736 131737 131738 131739 |
}
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
sParse.checkSchema = 0;
}
if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
if( sParse.pVdbe ){
sqlite3VdbeFinalize(sParse.pVdbe);
|
| ︙ | ︙ | |||
131865 131866 131867 131868 131869 131870 131871 |
if( iOffset>0 ){
sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
VdbeComment((v, "OFFSET"));
}
}
/*
| | | | > | > > > > > > > > | > > > > > > > > | > > > > > > > > > > > > > > > > > | > | | > > | > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 132750 132751 132752 132753 132754 132755 132756 132757 132758 132759 132760 132761 132762 132763 132764 132765 132766 132767 132768 132769 132770 132771 132772 132773 132774 132775 132776 132777 132778 132779 132780 132781 132782 132783 132784 132785 132786 132787 132788 132789 132790 132791 132792 132793 132794 132795 132796 132797 132798 132799 132800 132801 132802 132803 132804 132805 132806 132807 132808 132809 132810 132811 132812 132813 132814 132815 132816 132817 132818 132819 132820 132821 132822 132823 132824 132825 132826 132827 132828 132829 132830 132831 132832 132833 132834 132835 132836 132837 132838 132839 132840 132841 132842 132843 132844 132845 132846 132847 132848 132849 132850 132851 132852 132853 132854 132855 132856 132857 132858 132859 132860 132861 132862 132863 132864 132865 132866 132867 132868 132869 132870 132871 132872 132873 132874 132875 132876 132877 132878 132879 132880 132881 132882 132883 132884 132885 132886 132887 132888 132889 132890 132891 132892 132893 132894 132895 132896 132897 132898 132899 132900 132901 132902 132903 132904 132905 132906 132907 132908 132909 132910 132911 132912 |
if( iOffset>0 ){
sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
VdbeComment((v, "OFFSET"));
}
}
/*
** Add code that will check to make sure the array of registers starting at
** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
** distinct aggregates ("SELECT count(DISTINCT <expr>) ..."). Three strategies
** are available. Which is used depends on the value of parameter eTnctType,
** as follows:
**
** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
** Build an ephemeral table that contains all entries seen before and
** skip entries which have been seen before.
**
** Parameter iTab is the cursor number of an ephemeral table that must
** be opened before the VM code generated by this routine is executed.
** The ephemeral cursor table is queried for a record identical to the
** record formed by the current array of registers. If one is found,
** jump to VM address addrRepeat. Otherwise, insert a new record into
** the ephemeral cursor and proceed.
**
** The returned value in this case is a copy of parameter iTab.
**
** WHERE_DISTINCT_ORDERED:
** In this case rows are being delivered sorted order. The ephermal
** table is not required. Instead, the current set of values
** is compared against previous row. If they match, the new row
** is not distinct and control jumps to VM address addrRepeat. Otherwise,
** the VM program proceeds with processing the new row.
**
** The returned value in this case is the register number of the first
** in an array of registers used to store the previous result row so that
** it can be compared to the next. The caller must ensure that this
** register is initialized to NULL. (The fixDistinctOpenEph() routine
** will take care of this initialization.)
**
** WHERE_DISTINCT_UNIQUE:
** In this case it has already been determined that the rows are distinct.
** No special action is required. The return value is zero.
**
** Parameter pEList is the list of expressions used to generated the
** contents of each row. It is used by this routine to determine (a)
** how many elements there are in the array of registers and (b) the
** collation sequences that should be used for the comparisons if
** eTnctType is WHERE_DISTINCT_ORDERED.
*/
static int codeDistinct(
Parse *pParse, /* Parsing and code generating context */
int eTnctType, /* WHERE_DISTINCT_* value */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
ExprList *pEList, /* Expression for each element */
int regElem /* First element */
){
int iRet = 0;
int nResultCol = pEList->nExpr;
Vdbe *v = pParse->pVdbe;
switch( eTnctType ){
case WHERE_DISTINCT_ORDERED: {
int i;
int iJump; /* Jump destination */
int regPrev; /* Previous row content */
/* Allocate space for the previous row */
iRet = regPrev = pParse->nMem+1;
pParse->nMem += nResultCol;
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
for(i=0; i<nResultCol; i++){
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
if( i<nResultCol-1 ){
sqlite3VdbeAddOp3(v, OP_Ne, regElem+i, iJump, regPrev+i);
VdbeCoverage(v);
}else{
sqlite3VdbeAddOp3(v, OP_Eq, regElem+i, addrRepeat, regPrev+i);
VdbeCoverage(v);
}
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
}
assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1);
break;
}
case WHERE_DISTINCT_UNIQUE: {
/* nothing to do */
break;
}
default: {
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, r1);
iRet = iTab;
break;
}
}
return iRet;
}
/*
** This routine runs after codeDistinct(). It makes necessary
** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
** routine made use of. This processing must be done separately since
** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
** laid down.
**
** WHERE_DISTINCT_NOOP:
** WHERE_DISTINCT_UNORDERED:
**
** No adjustments necessary. This function is a no-op.
**
** WHERE_DISTINCT_UNIQUE:
**
** The ephemeral table is not needed. So change the
** OP_OpenEphemeral opcode into an OP_Noop.
**
** WHERE_DISTINCT_ORDERED:
**
** The ephemeral table is not needed. But we do need register
** iVal to be initialized to NULL. So change the OP_OpenEphemeral
** into an OP_Null on the iVal register.
*/
static void fixDistinctOpenEph(
Parse *pParse, /* Parsing and code generating context */
int eTnctType, /* WHERE_DISTINCT_* value */
int iVal, /* Value returned by codeDistinct() */
int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
){
if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
}
if( eTnctType==WHERE_DISTINCT_ORDERED ){
/* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
** bit on the first register of the previous value. This will cause the
** OP_Ne added in codeDistinct() to always fail on the first iteration of
** the loop even if the first row is all NULLs. */
VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
pOp->opcode = OP_Null;
pOp->p1 = 1;
pOp->p2 = iVal;
}
}
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/*
** This function is called as part of inner-loop generation for a SELECT
** statement with an ORDER BY that is not optimized by an index. It
** determines the expressions, if any, that the sorter-reference
|
| ︙ | ︙ | |||
132137 132138 132139 132140 132141 132142 132143 |
}
/* If the DISTINCT keyword was present on the SELECT statement
** and this row has been seen before, then do not make this row
** part of the result.
*/
if( hasDistinct ){
| | < < < < | < < | | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 133146 133147 133148 133149 133150 133151 133152 133153 133154 133155 133156 133157 133158 133159 133160 133161 133162 133163 133164 |
}
/* If the DISTINCT keyword was present on the SELECT statement
** and this row has been seen before, then do not make this row
** part of the result.
*/
if( hasDistinct ){
int eType = pDistinct->eTnctType;
int iTab = pDistinct->tabTnct;
assert( nResultCol==p->pEList->nExpr );
iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
}
switch( eDest ){
/* In this mode, write each query result to the key of the temporary
|
| ︙ | ︙ | |||
132855 132856 132857 132858 132859 132860 132861 |
assert( pTab && 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.
*/
| | > > > > > > | 133816 133817 133818 133819 133820 133821 133822 133823 133824 133825 133826 133827 133828 133829 133830 133831 133832 133833 133834 133835 133836 |
assert( pTab && 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
&& iCol>=0
#else
&& ALWAYS(iCol>=0)
#endif
){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
*/
NameContext sNC;
Expr *p = pS->pEList->a[iCol].pExpr;
sNC.pSrcList = pS->pSrc;
|
| ︙ | ︙ | |||
132997 132998 132999 133000 133001 133002 133003 | ** result column name is just the table column ** name: COLUMN. Otherwise use zSpan. ** ** full=ON, short=ANY: If the result refers directly to a table column, ** then the result column name with the table name ** prefix, ex: TABLE.COLUMN. Otherwise use zSpan. */ | | | 133964 133965 133966 133967 133968 133969 133970 133971 133972 133973 133974 133975 133976 133977 133978 |
** result column name is just the table column
** name: COLUMN. Otherwise use zSpan.
**
** full=ON, short=ANY: If the result refers directly to a table column,
** then the result column name with the table name
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
SQLITE_PRIVATE void sqlite3GenerateColumnNames(
Parse *pParse, /* Parser context */
Select *pSelect /* Generate column names for this SELECT statement */
){
Vdbe *v = pParse->pVdbe;
int i;
Table *pTab;
SrcList *pTabList;
|
| ︙ | ︙ | |||
133087 133088 133089 133090 133091 133092 133093 | ** The only guarantee that SQLite makes about column names is that if the ** column has an AS clause assigning it a name, that will be the name used. ** That is the only documented guarantee. However, countless applications ** developed over the years have made baseless assumptions about column names ** and will break if those assumptions changes. Hence, use extreme caution ** when modifying this routine to avoid breaking legacy. ** | | | 134054 134055 134056 134057 134058 134059 134060 134061 134062 134063 134064 134065 134066 134067 134068 |
** The only guarantee that SQLite makes about column names is that if the
** column has an AS clause assigning it a name, that will be the name used.
** That is the only documented guarantee. However, countless applications
** developed over the years have made baseless assumptions about column names
** and will break if those assumptions changes. Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
** See Also: sqlite3GenerateColumnNames()
*/
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
ExprList *pEList, /* Expr list from which to derive column names */
i16 *pnCol, /* Write the number of columns here */
Column **paCol /* Write the new column list here */
){
|
| ︙ | ︙ | |||
133785 133786 133787 133788 133789 133790 133791 |
#endif
/* Generate code for the left and right SELECT statements.
*/
switch( p->op ){
case TK_ALL: {
int addr = 0;
| | > > | 134752 134753 134754 134755 134756 134757 134758 134759 134760 134761 134762 134763 134764 134765 134766 134767 134768 134769 134770 134771 134772 134773 134774 134775 134776 134777 134778 134779 134780 134781 134782 134783 134784 134785 134786 134787 134788 134789 |
#endif
/* Generate code for the left and right SELECT statements.
*/
switch( p->op ){
case TK_ALL: {
int addr = 0;
int nLimit = 0; /* Initialize to suppress harmless compiler warning */
assert( !pPrior->pLimit );
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlite3Select(pParse, pPrior, &dest);
pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
}
p->pPrior = 0;
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
if( p->iLimit ){
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
VdbeComment((v, "Jump ahead if LIMIT reached"));
if( p->iOffset ){
sqlite3VdbeAddOp3(v, OP_OffsetLimit,
p->iLimit, p->iOffset+1, p->iOffset);
}
}
ExplainQueryPlan((pParse, 1, "UNION ALL"));
SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
rc = sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( p->pLimit
&& sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
|
| ︙ | ︙ | |||
133859 133860 133861 133862 133863 133864 133865 133866 133867 133868 133869 133870 133871 133872 133873 133874 133875 133876 133877 133878 133879 133880 133881 133882 133883 133884 133885 133886 133887 133888 133889 133890 133891 |
}
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT statement
*/
if( p->op==TK_EXCEPT ){
op = SRT_Except;
}else{
assert( p->op==TK_UNION );
op = SRT_Union;
}
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
if( p->op==TK_UNION ){
| > > | 134828 134829 134830 134831 134832 134833 134834 134835 134836 134837 134838 134839 134840 134841 134842 134843 134844 134845 134846 134847 134848 134849 134850 134851 134852 134853 134854 134855 134856 134857 134858 134859 134860 134861 134862 |
}
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT statement
*/
if( p->op==TK_EXCEPT ){
op = SRT_Except;
}else{
assert( p->op==TK_UNION );
op = SRT_Union;
}
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
rc = sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
if( p->op==TK_UNION ){
|
| ︙ | ︙ | |||
133938 133939 133940 133941 133942 133943 133944 133945 133946 133947 133948 133949 133950 133951 133952 133953 133954 133955 133956 133957 133958 133959 133960 133961 133962 133963 133964 133965 133966 133967 |
p->addrOpenEphm[0] = addr;
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT into temporary table "tab2"
*/
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
assert( p->addrOpenEphm[1] == -1 );
p->addrOpenEphm[1] = addr;
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
if( p->nSelectRow>pPrior->nSelectRow ){
p->nSelectRow = pPrior->nSelectRow;
}
| > > | 134909 134910 134911 134912 134913 134914 134915 134916 134917 134918 134919 134920 134921 134922 134923 134924 134925 134926 134927 134928 134929 134930 134931 134932 134933 134934 134935 134936 134937 134938 134939 134940 |
p->addrOpenEphm[0] = addr;
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT into temporary table "tab2"
*/
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
assert( p->addrOpenEphm[1] == -1 );
p->addrOpenEphm[1] = addr;
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
rc = sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
if( p->nSelectRow>pPrior->nSelectRow ){
p->nSelectRow = pPrior->nSelectRow;
}
|
| ︙ | ︙ | |||
134586 134587 134588 134589 134590 134591 134592 134593 134594 134595 134596 134597 134598 134599 |
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
pPrior->pNext = p;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
ExplainQueryPlanPop(pParse);
return pParse->nErr!=0;
}
#endif
| > > > | 135559 135560 135561 135562 135563 135564 135565 135566 135567 135568 135569 135570 135571 135572 135573 135574 135575 |
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
pPrior->pNext = p;
sqlite3ExprListDelete(db, pPrior->pOrderBy);
pPrior->pOrderBy = 0;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
ExplainQueryPlanPop(pParse);
return pParse->nErr!=0;
}
#endif
|
| ︙ | ︙ | |||
134641 134642 134643 134644 134645 134646 134647 134648 134649 |
){
pExpr->iRightJoinTable = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
| > | > > > > > > | | < | | | | | | | < | 135617 135618 135619 135620 135621 135622 135623 135624 135625 135626 135627 135628 135629 135630 135631 135632 135633 135634 135635 135636 135637 135638 135639 135640 135641 135642 135643 135644 135645 135646 135647 135648 135649 135650 135651 135652 135653 135654 135655 135656 135657 135658 135659 135660 135661 135662 135663 135664 135665 135666 135667 135668 135669 135670 135671 135672 135673 135674 135675 135676 135677 |
){
pExpr->iRightJoinTable = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else
#endif
{
Expr *pNew;
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
assert( pExpr->pRight==0 );
if( sqlite3ExprIsVector(pCopy) ){
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
sqlite3 *db = pSubst->pParse->db;
if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
memset(&ifNullRow, 0, sizeof(ifNullRow));
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pNew);
return pExpr;
}
if( pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
if( ExprHasProperty(pExpr,EP_FromJoin) ){
sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
(pColl ? pColl->zName : "BINARY")
);
}
ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
pExpr->iTable = pSubst->iNewTable;
}
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
|
| ︙ | ︙ | |||
134801 134802 134803 134804 134805 134806 134807 |
int iExcept /* FROM clause item to skip */
){
int i;
SrcItem *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( i!=iExcept ){
Select *p;
| > > > | | 135782 135783 135784 135785 135786 135787 135788 135789 135790 135791 135792 135793 135794 135795 135796 135797 135798 135799 |
int iExcept /* FROM clause item to skip */
){
int i;
SrcItem *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
if( i!=iExcept ){
Select *p;
if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
aCsrMap[pItem->iCursor] = pParse->nTab++;
}
pItem->iCursor = aCsrMap[pItem->iCursor];
for(p=pItem->pSelect; p; p=p->pPrior){
srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
}
}
}
}
|
| ︙ | ︙ | |||
135241 135242 135243 135244 135245 135246 135247 |
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
pNew->selId = ++pParse->nSelect;
| | | 136225 136226 136227 136228 136229 136230 136231 136232 136233 136234 136235 136236 136237 136238 136239 |
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
pNew->selId = ++pParse->nSelect;
if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
renumberCursors(pParse, pNew, iFrom, aCsrMap);
}
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
|
| ︙ | ︙ | |||
135442 135443 135444 135445 135446 135447 135448 135449 135450 135451 135452 135453 135454 135455 |
** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
*/
typedef struct WhereConst WhereConst;
struct WhereConst {
Parse *pParse; /* Parsing context */
int nConst; /* Number for COLUMN=CONSTANT terms */
int nChng; /* Number of times a constant is propagated */
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
};
/*
** Add a new entry to the pConst object. Except, do not add duplicate
** pColumn entires. Also, do not add if doing so would not be appropriate.
**
| > | 136426 136427 136428 136429 136430 136431 136432 136433 136434 136435 136436 136437 136438 136439 136440 |
** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
*/
typedef struct WhereConst WhereConst;
struct WhereConst {
Parse *pParse; /* Parsing context */
int nConst; /* Number for COLUMN=CONSTANT terms */
int nChng; /* Number of times a constant is propagated */
int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
};
/*
** Add a new entry to the pConst object. Except, do not add duplicate
** pColumn entires. Also, do not add if doing so would not be appropriate.
**
|
| ︙ | ︙ | |||
135480 135481 135482 135483 135484 135485 135486 135487 135488 135489 135490 135491 135492 135493 135494 135495 135496 135497 135498 135499 135500 135501 135502 135503 135504 135505 135506 |
assert( pE2->op==TK_COLUMN );
if( pE2->iTable==pColumn->iTable
&& pE2->iColumn==pColumn->iColumn
){
return; /* Already present. Return without doing anything. */
}
}
pConst->nConst++;
pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
pConst->nConst*2*sizeof(Expr*));
if( pConst->apExpr==0 ){
pConst->nConst = 0;
}else{
pConst->apExpr[pConst->nConst*2-2] = pColumn;
pConst->apExpr[pConst->nConst*2-1] = pValue;
}
}
/*
** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression. For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
| > > > | | > | | | > > | > > > > < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 136465 136466 136467 136468 136469 136470 136471 136472 136473 136474 136475 136476 136477 136478 136479 136480 136481 136482 136483 136484 136485 136486 136487 136488 136489 136490 136491 136492 136493 136494 136495 136496 136497 136498 136499 136500 136501 136502 136503 136504 136505 136506 136507 136508 136509 136510 136511 136512 136513 136514 136515 136516 136517 136518 136519 136520 136521 136522 136523 136524 136525 136526 136527 136528 136529 136530 136531 136532 136533 136534 136535 136536 136537 136538 136539 136540 136541 136542 136543 136544 136545 136546 136547 136548 136549 136550 136551 136552 136553 136554 136555 136556 136557 136558 136559 136560 136561 136562 136563 136564 136565 136566 136567 136568 136569 136570 136571 136572 136573 136574 136575 136576 136577 136578 136579 136580 136581 136582 136583 136584 136585 136586 136587 136588 136589 136590 136591 136592 136593 136594 136595 |
assert( pE2->op==TK_COLUMN );
if( pE2->iTable==pColumn->iTable
&& pE2->iColumn==pColumn->iColumn
){
return; /* Already present. Return without doing anything. */
}
}
if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
pConst->bHasAffBlob = 1;
}
pConst->nConst++;
pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
pConst->nConst*2*sizeof(Expr*));
if( pConst->apExpr==0 ){
pConst->nConst = 0;
}else{
pConst->apExpr[pConst->nConst*2-2] = pColumn;
pConst->apExpr[pConst->nConst*2-1] = pValue;
}
}
/*
** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression. For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
if( NEVER(pExpr==0) ) return;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
findConstInWhere(pConst, pExpr->pLeft);
return;
}
if( pExpr->op!=TK_EQ ) return;
pRight = pExpr->pRight;
pLeft = pExpr->pLeft;
assert( pRight!=0 );
assert( pLeft!=0 );
if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
constInsert(pConst,pRight,pLeft,pExpr);
}
if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
constInsert(pConst,pLeft,pRight,pExpr);
}
}
/*
** This is a helper function for Walker callback propagateConstantExprRewrite().
**
** Argument pExpr is a candidate expression to be replaced by a value. If
** pExpr is equivalent to one of the columns named in pWalker->u.pConst,
** then overwrite it with the corresponding value. Except, do not do so
** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
** is SQLITE_AFF_BLOB.
*/
static int propagateConstantExprRewriteOne(
WhereConst *pConst,
Expr *pExpr,
int bIgnoreAffBlob
){
int i;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
testcase( ExprHasProperty(pExpr, EP_FromJoin) );
return WRC_Continue;
}
for(i=0; i<pConst->nConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
break;
}
/* A match is found. Add the EP_FixedCol property */
pConst->nChng++;
ExprClearProperty(pExpr, EP_Leaf);
ExprSetProperty(pExpr, EP_FixedCol);
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0);
break;
}
return WRC_Prune;
}
/*
** This is a Walker expression callback. pExpr is a node from the WHERE
** clause of a SELECT statement. This function examines pExpr to see if
** any substitutions based on the contents of pWalker->u.pConst should
** be made to pExpr or its immediate children.
**
** A substitution is made if:
**
** + pExpr is a column with an affinity other than BLOB that matches
** one of the columns in pWalker->u.pConst, or
**
** + pExpr is a binary comparison operator (=, <=, >=, <, >) that
** uses an affinity other than TEXT and one of its immediate
** children is a column that matches one of the columns in
** pWalker->u.pConst.
*/
static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
WhereConst *pConst = pWalker->u.pConst;
assert( TK_GT==TK_EQ+1 );
assert( TK_LE==TK_EQ+2 );
assert( TK_LT==TK_EQ+3 );
assert( TK_GE==TK_EQ+4 );
if( pConst->bHasAffBlob ){
if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE)
|| pExpr->op==TK_IS
){
propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0);
if( sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){
propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0);
}
}
}
return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob);
}
/*
** The WHERE-clause constant propagation optimization.
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
** CONSTANT=COLUMN that are top-level AND-connected terms that are not
** part of a ON clause from a LEFT JOIN, then throughout the query
|
| ︙ | ︙ | |||
135587 135588 135589 135590 135591 135592 135593 135594 135595 135596 135597 135598 135599 135600 135601 135602 135603 135604 135605 135606 135607 135608 135609 135610 135611 135612 135613 |
** is false because it uses text affinity and '0123' is not the same as '123'.
** To work around this, the expression tree is not actually changed from
** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol
** and the "123" value is hung off of the pLeft pointer. Code generator
** routines know to generate the constant "123" instead of looking up the
** column value. Also, to avoid collation problems, this optimization is
** only attempted if the "a=123" term uses the default BINARY collation.
*/
static int propagateConstants(
Parse *pParse, /* The parsing context */
Select *p /* The query in which to propagate constants */
){
WhereConst x;
Walker w;
int nChng = 0;
x.pParse = pParse;
do{
x.nConst = 0;
x.nChng = 0;
x.apExpr = 0;
findConstInWhere(&x, p->pWhere);
if( x.nConst ){
memset(&w, 0, sizeof(w));
w.pParse = pParse;
w.xExprCallback = propagateConstantExprRewrite;
w.xSelectCallback = sqlite3SelectWalkNoop;
w.xSelectCallback2 = 0;
| > > > > > > > > > > > > > > > > | 136618 136619 136620 136621 136622 136623 136624 136625 136626 136627 136628 136629 136630 136631 136632 136633 136634 136635 136636 136637 136638 136639 136640 136641 136642 136643 136644 136645 136646 136647 136648 136649 136650 136651 136652 136653 136654 136655 136656 136657 136658 136659 136660 |
** is false because it uses text affinity and '0123' is not the same as '123'.
** To work around this, the expression tree is not actually changed from
** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol
** and the "123" value is hung off of the pLeft pointer. Code generator
** routines know to generate the constant "123" instead of looking up the
** column value. Also, to avoid collation problems, this optimization is
** only attempted if the "a=123" term uses the default BINARY collation.
**
** 2021-05-25 forum post 6a06202608: Another troublesome case is...
**
** CREATE TABLE t1(x);
** INSERT INTO t1 VALUES(10.0);
** SELECT 1 FROM t1 WHERE x=10 AND x LIKE 10;
**
** The query should return no rows, because the t1.x value is '10.0' not '10'
** and '10.0' is not LIKE '10'. But if we are not careful, the first WHERE
** term "x=10" will cause the second WHERE term to become "10 LIKE 10",
** resulting in a false positive. To avoid this, constant propagation for
** columns with BLOB affinity is only allowed if the constant is used with
** operators ==, <=, <, >=, >, or IS in a way that will cause the correct
** type conversions to occur. See logic associated with the bHasAffBlob flag
** for details.
*/
static int propagateConstants(
Parse *pParse, /* The parsing context */
Select *p /* The query in which to propagate constants */
){
WhereConst x;
Walker w;
int nChng = 0;
x.pParse = pParse;
do{
x.nConst = 0;
x.nChng = 0;
x.apExpr = 0;
x.bHasAffBlob = 0;
findConstInWhere(&x, p->pWhere);
if( x.nConst ){
memset(&w, 0, sizeof(w));
w.pParse = pParse;
w.xExprCallback = propagateConstantExprRewrite;
w.xSelectCallback = sqlite3SelectWalkNoop;
w.xSelectCallback2 = 0;
|
| ︙ | ︙ | |||
136036 136037 136038 136039 136040 136041 136042 136043 136044 136045 136046 136047 136048 136049 136050 136051 |
int i;
for(i=0; i<p->nCte; i++){
if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
*ppContext = p;
return &p->a[i];
}
}
}
return 0;
}
/* The code generator maintains a stack of active WITH clauses
** with the inner-most WITH clause being at the top of the stack.
**
** This routine pushes the WITH clause passed as the second argument
** onto the top of the stack. If argument bFree is true, then this
| > | | > | | | > | 137083 137084 137085 137086 137087 137088 137089 137090 137091 137092 137093 137094 137095 137096 137097 137098 137099 137100 137101 137102 137103 137104 137105 137106 137107 137108 137109 137110 137111 137112 137113 137114 137115 137116 137117 137118 |
int i;
for(i=0; i<p->nCte; i++){
if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
*ppContext = p;
return &p->a[i];
}
}
if( p->bView ) break;
}
return 0;
}
/* The code generator maintains a stack of active WITH clauses
** with the inner-most WITH clause being at the top of the stack.
**
** This routine pushes the WITH clause passed as the second argument
** onto the top of the stack. If argument bFree is true, then this
** WITH clause will never be popped from the stack but should instead
** be freed along with the Parse object. In other cases, when
** bFree==0, the With object will be freed along with the SELECT
** statement with which it is associated.
*/
SQLITE_PRIVATE void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
if( pParse->nErr==0 ){
assert( pParse->pWith!=pWith );
pWith->pOuter = pParse->pWith;
pParse->pWith = pWith;
}
if( bFree ){
sqlite3ParserAddCleanup(pParse,
(void(*)(sqlite3*,void*))sqlite3WithDelete,
pWith);
testcase( pParse->earlyCleanup );
}
}
|
| ︙ | ︙ | |||
136090 136091 136092 136093 136094 136095 136096 136097 136098 136099 136100 136101 136102 136103 136104 136105 136106 136107 136108 |
Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
if( pParse->pWith==0 ){
/* There are no WITH clauses in the stack. No match is possible */
return 0;
}
if( pFrom->zDatabase!=0 ){
/* The FROM term contains a schema qualifier (ex: main.t1) and so
** it cannot possibly be a CTE reference. */
return 0;
}
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
| > > > > > > > > > > > > > | 137140 137141 137142 137143 137144 137145 137146 137147 137148 137149 137150 137151 137152 137153 137154 137155 137156 137157 137158 137159 137160 137161 137162 137163 137164 137165 137166 137167 137168 137169 137170 137171 |
Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
if( pParse->pWith==0 ){
/* There are no WITH clauses in the stack. No match is possible */
return 0;
}
if( pParse->nErr ){
/* Prior errors might have left pParse->pWith in a goofy state, so
** go no further. */
return 0;
}
if( pFrom->zDatabase!=0 ){
/* The FROM term contains a schema qualifier (ex: main.t1) and so
** it cannot possibly be a CTE reference. */
return 0;
}
if( pFrom->fg.notCte ){
/* The FROM term is specifically excluded from matching a CTE.
** (1) It is part of a trigger that used to have zDatabase but had
** zDatabase removed by sqlite3FixTriggerStep().
** (2) This is the first term in the FROM clause of an UPDATE.
*/
return 0;
}
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
|
| ︙ | ︙ | |||
136244 136245 136246 136247 136248 136249 136250 | ** If the SELECT passed as the second argument has an associated WITH ** clause, pop it from the stack stored as part of the Parse object. ** ** This function is used as the xSelectCallback2() callback by ** sqlite3SelectExpand() when walking a SELECT tree to resolve table ** names and other FROM clause elements. */ | | < < | 137307 137308 137309 137310 137311 137312 137313 137314 137315 137316 137317 137318 137319 137320 137321 137322 137323 137324 137325 137326 137327 137328 137329 137330 |
** If the SELECT passed as the second argument has an associated WITH
** clause, pop it from the stack stored as part of the Parse object.
**
** This function is used as the xSelectCallback2() callback by
** sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements.
*/
SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
assert( pParse->pWith==pWith || pParse->nErr );
pParse->pWith = pWith->pOuter;
}
}
}
#endif
/*
** The SrcList_item structure passed as the second argument represents a
** sub-query in the FROM clause of a SELECT statement. This function
** allocates and populates the SrcList_item.pTab object. If successful,
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
|
| ︙ | ︙ | |||
136282 136283 136284 136285 136286 136287 136288 |
}else{
pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
}
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
| > > | > > > > | 137343 137344 137345 137346 137347 137348 137349 137350 137351 137352 137353 137354 137355 137356 137357 137358 137359 137360 137361 137362 137363 |
}else{
pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
}
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
/* The usual case - do not allow ROWID on a subquery */
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
|
| ︙ | ︙ | |||
136336 136337 136338 136339 136340 136341 136342 136343 136344 136345 136346 136347 136348 136349 |
}
if( pWalker->eCode ){
/* Renumber selId because it has been copied from a view */
p->selId = ++pParse->nSelect;
}
pTabList = p->pSrc;
pEList = p->pEList;
sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
*/
sqlite3SrcListAssignCursors(pParse, pTabList);
| > > > > > > > > > | 137403 137404 137405 137406 137407 137408 137409 137410 137411 137412 137413 137414 137415 137416 137417 137418 137419 137420 137421 137422 137423 137424 137425 |
}
if( pWalker->eCode ){
/* Renumber selId because it has been copied from a view */
p->selId = ++pParse->nSelect;
}
pTabList = p->pSrc;
pEList = p->pEList;
if( pParse->pWith && (p->selFlags & SF_View) ){
if( p->pWith==0 ){
p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
if( p->pWith==0 ){
return WRC_Abort;
}
}
p->pWith->bView = 1;
}
sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
*/
sqlite3SrcListAssignCursors(pParse, pTabList);
|
| ︙ | ︙ | |||
136636 136637 136638 136639 136640 136641 136642 |
w.pParse = pParse;
if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
w.xSelectCallback = convertCompoundSelectToSubquery;
w.xSelectCallback2 = 0;
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
| | | 137712 137713 137714 137715 137716 137717 137718 137719 137720 137721 137722 137723 137724 137725 137726 |
w.pParse = pParse;
if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
w.xSelectCallback = convertCompoundSelectToSubquery;
w.xSelectCallback2 = 0;
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
w.xSelectCallback2 = sqlite3SelectPopWith;
w.eCode = 0;
sqlite3WalkSelect(&w, pSelect);
}
#ifndef SQLITE_OMIT_SUBQUERY
/*
|
| ︙ | ︙ | |||
136769 136770 136771 136772 136773 136774 136775 |
assert( !ExprHasProperty(pE, EP_xIsSelect) );
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);
| | | > > | 137845 137846 137847 137848 137849 137850 137851 137852 137853 137854 137855 137856 137857 137858 137859 137860 137861 137862 |
assert( !ExprHasProperty(pE, EP_xIsSelect) );
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,
pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
pFunc->pFunc->zName));
}
}
}
}
/*
** Invoke the OP_AggFinalize opcode for every aggregate function
|
| ︙ | ︙ | |||
136802 136803 136804 136805 136806 136807 136808 | ** the current cursor position. ** ** If regAcc is non-zero and there are no min() or max() aggregates ** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator ** registers if register regAcc contains 0. The caller will take care ** of setting and clearing regAcc. */ | | > > > > > | 137880 137881 137882 137883 137884 137885 137886 137887 137888 137889 137890 137891 137892 137893 137894 137895 137896 137897 137898 137899 |
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(
Parse *pParse,
int regAcc,
AggInfo *pAggInfo,
int eDistinctType
){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
int addrHitTest = 0;
struct AggInfo_func *pF;
struct AggInfo_col *pC;
|
| ︙ | ︙ | |||
136848 136849 136850 136851 136852 136853 136854 |
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
}else{
nArg = 0;
regAgg = 0;
}
| | | < | | 137931 137932 137933 137934 137935 137936 137937 137938 137939 137940 137941 137942 137943 137944 137945 137946 137947 137948 137949 137950 |
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
}else{
nArg = 0;
regAgg = 0;
}
if( pF->iDistinct>=0 && pList ){
if( addrNext==0 ){
addrNext = sqlite3VdbeMakeLabel(pParse);
}
pF->iDistinct = codeDistinct(pParse, eDistinctType,
pF->iDistinct, addrNext, pList, regAgg);
}
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl = 0;
struct ExprList_item *pItem;
int j;
assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */
for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
|
| ︙ | ︙ | |||
136906 136907 136908 136909 136910 136911 136912 |
static void explainSimpleCount(
Parse *pParse, /* Parse context */
Table *pTab, /* Table being queried */
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
| | | 137988 137989 137990 137991 137992 137993 137994 137995 137996 137997 137998 137999 138000 138001 138002 |
static void explainSimpleCount(
Parse *pParse, /* Parse context */
Table *pTab, /* Table being queried */
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
);
}
}
#else
|
| ︙ | ︙ | |||
137217 137218 137219 137220 137221 137222 137223 |
);
goto select_end;
}
}
}
if( pDest->eDest==SRT_Output ){
| | | < | 138299 138300 138301 138302 138303 138304 138305 138306 138307 138308 138309 138310 138311 138312 138313 138314 138315 138316 138317 |
);
goto select_end;
}
}
}
if( pDest->eDest==SRT_Output ){
sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( sqlite3WindowRewrite(pParse, p) ){
assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED
if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
|
| ︙ | ︙ | |||
137348 137349 137350 137351 137352 137353 137354 | #endif /* Do the WHERE-clause constant propagation optimization if this is ** a join. No need to speed time on this operation for non-join queries ** as the equivalent optimization will be handled by query planner in ** sqlite3WhereBegin(). */ | | > | 138429 138430 138431 138432 138433 138434 138435 138436 138437 138438 138439 138440 138441 138442 138443 138444 |
#endif
/* Do the WHERE-clause constant propagation optimization if this is
** a join. No need to speed time on this operation for non-join queries
** as the equivalent optimization will be handled by query planner in
** sqlite3WhereBegin().
*/
if( p->pWhere!=0
&& p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
|
| ︙ | ︙ | |||
137411 137412 137413 137414 137415 137416 137417 |
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Generate code for all sub-queries in the FROM clause
*/
pSub = pItem->pSelect;
if( pSub==0 ) continue;
| | < < < < < < < < < < < | | 138493 138494 138495 138496 138497 138498 138499 138500 138501 138502 138503 138504 138505 138506 138507 138508 |
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Generate code for all sub-queries in the FROM clause
*/
pSub = pItem->pSelect;
if( pSub==0 ) continue;
/* The code for a subquery should only be generated once. */
assert( pItem->addrFillSub==0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
** may contain expression trees of at most
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
** more conservative than necessary, but much easier than enforcing
** an exact limit.
|
| ︙ | ︙ | |||
137479 137480 137481 137482 137483 137484 137485 |
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
| | | | 138550 138551 138552 138553 138554 138555 138556 138557 138558 138559 138560 138561 138562 138563 138564 138565 138566 138567 |
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%!S", pItem));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
|
| ︙ | ︙ | |||
137510 137511 137512 137513 137514 137515 137516 |
** this same FROM clause. Reuse it. */
if( pPrior->addrFillSub ){
sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
}
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
| | < | | | | | 138581 138582 138583 138584 138585 138586 138587 138588 138589 138590 138591 138592 138593 138594 138595 138596 138597 138598 138599 138600 138601 138602 138603 138604 138605 138606 138607 138608 138609 138610 138611 138612 138613 138614 138615 138616 138617 138618 138619 138620 |
** this same FROM clause. Reuse it. */
if( pPrior->addrFillSub ){
sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
}
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
/* Materialize the view. If the view is not correlated, generate a
** subroutine to do the materialization so that subsequent uses of
** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
int retAddr;
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
if( pItem->fg.isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
VdbeComment((v, "materialize %!S", pItem));
}else{
VdbeNoopComment((v, "materialize %!S", pItem));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %!S", pItem));
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
CteUse *pCteUse = pItem->u2.pCteUse;
pCteUse->addrM9e = pItem->addrFillSub;
pCteUse->regRtn = pItem->regReturn;
pCteUse->iCur = pItem->iCursor;
|
| ︙ | ︙ | |||
137886 137887 137888 137889 137890 137891 137892 137893 137894 137895 137896 137897 137898 137899 |
int addrOutputRow; /* Start of subroutine that outputs a result row */
int regOutputRow; /* Return address register for output subroutine */
int addrSetAbort; /* Set the abort flag and return */
int addrTopOfLoop; /* Top of the input loop */
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
int regReset; /* Return address register for reset subroutine */
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
** that we do not need it after all, the OP_SorterOpen instruction
** will be converted into a Noop.
*/
pAggInfo->sortingIdx = pParse->nTab++;
| > > > > > > > > > > > > > > | 138956 138957 138958 138959 138960 138961 138962 138963 138964 138965 138966 138967 138968 138969 138970 138971 138972 138973 138974 138975 138976 138977 138978 138979 138980 138981 138982 138983 |
int addrOutputRow; /* Start of subroutine that outputs a result row */
int regOutputRow; /* Return address register for output subroutine */
int addrSetAbort; /* Set the abort flag and return */
int addrTopOfLoop; /* Top of the input loop */
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
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
&& pAggInfo->aFunc[0].pFExpr->x.pList
){
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;
}
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
** that we do not need it after all, the OP_SorterOpen instruction
** will be converted into a Noop.
*/
pAggInfo->sortingIdx = pParse->nTab++;
|
| ︙ | ︙ | |||
137922 137923 137924 137925 137926 137927 137928 |
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
| | | | > > > > | 139006 139007 139008 139009 139010 139011 139012 139013 139014 139015 139016 139017 139018 139019 139020 139021 139022 139023 139024 139025 139026 139027 |
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDistinct);
goto select_end;
}
eDist = sqlite3WhereIsDistinct(pWInfo);
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
*/
groupBySort = 0;
|
| ︙ | ︙ | |||
138043 138044 138045 138046 138047 138048 138049 |
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
VdbeComment((v, "reset accumulator"));
/* Update the aggregate accumulators based on the content of
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
| | > | 139131 139132 139133 139134 139135 139136 139137 139138 139139 139140 139141 139142 139143 139144 139145 139146 139147 139148 139149 139150 139151 139152 139153 139154 139155 139156 139157 139158 139159 |
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
VdbeComment((v, "reset accumulator"));
/* Update the aggregate accumulators based on the content of
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
/* End of the loop
*/
if( groupBySort ){
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
sqlite3ExprListDelete(db, pDistinct);
/* Output the final row of result
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output final row"));
/* Jump over the subroutines
|
| ︙ | ︙ | |||
138100 138101 138102 138103 138104 138105 138106 138107 138108 138109 138110 138111 138112 138113 |
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
/* If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
| > > > > | 139189 139190 139191 139192 139193 139194 139195 139196 139197 139198 139199 139200 139201 139202 139203 139204 139205 139206 |
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
if( eDist!=WHERE_DISTINCT_NOOP ){
struct AggInfo_func *pF = &pAggInfo->aFunc[0];
fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
}
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
/* If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
|
| ︙ | ︙ | |||
138163 138164 138165 138166 138167 138168 138169 138170 138171 138172 138173 138174 138175 138176 |
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
** will contain 0 the first time the inner loop runs, and 1 thereafter.
** The code generated by updateAccumulator() uses this to ensure
** that the accumulator registers are (a) updated only once if
** there are no min() or max functions or (b) always updated for the
| > > > | 139256 139257 139258 139259 139260 139261 139262 139263 139264 139265 139266 139267 139268 139269 139270 139271 139272 |
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
ExprList *pDistinct = 0;
u16 distFlag = 0;
int eDist;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
** will contain 0 the first time the inner loop runs, and 1 thereafter.
** The code generated by updateAccumulator() uses this to ensure
** that the accumulator registers are (a) updated only once if
** there are no min() or max functions or (b) always updated for the
|
| ︙ | ︙ | |||
138186 138187 138188 138189 138190 138191 138192 138193 138194 138195 138196 138197 138198 138199 138200 138201 138202 138203 138204 138205 138206 138207 138208 138209 138210 138211 |
break;
}
}
if( i==pAggInfo->nFunc ){
regAcc = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
}
/* 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.
*/
assert( p->pGroupBy==0 );
resetAccumulator(pParse, pAggInfo);
/* If this query is a candidate for the min/max optimization, then
** minMaxFlag will have been previously set to either
** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
** be an appropriate ORDER BY expression for the optimization.
*/
assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
| > > > | > | > > > > > | 139282 139283 139284 139285 139286 139287 139288 139289 139290 139291 139292 139293 139294 139295 139296 139297 139298 139299 139300 139301 139302 139303 139304 139305 139306 139307 139308 139309 139310 139311 139312 139313 139314 139315 139316 139317 139318 139319 139320 139321 139322 139323 139324 139325 139326 139327 139328 139329 |
break;
}
}
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.
*/
assert( p->pGroupBy==0 );
resetAccumulator(pParse, pAggInfo);
/* If this query is a candidate for the min/max optimization, then
** minMaxFlag will have been previously set to either
** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
** be an appropriate ORDER BY expression for the optimization.
*/
assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
pDistinct, minMaxFlag|distFlag, 0);
if( pWInfo==0 ){
goto select_end;
}
SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
eDist = sqlite3WhereIsDistinct(pWInfo);
updateAccumulator(pParse, regAcc, pAggInfo, eDist);
if( eDist!=WHERE_DISTINCT_NOOP ){
struct AggInfo_func *pF = &pAggInfo->aFunc[0];
fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
}
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( minMaxFlag ){
sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo);
|
| ︙ | ︙ | |||
138255 138256 138257 138258 138259 138260 138261 138262 138263 138264 138265 138266 138267 138268 |
** set the return code to 1. Otherwise 0. */
rc = (pParse->nErr>0);
/* Control jumps to here if an error is encountered above, or upon
** successful coding of the SELECT.
*/
select_end:
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
| > > | 139360 139361 139362 139363 139364 139365 139366 139367 139368 139369 139370 139371 139372 139373 139374 139375 |
** set the return code to 1. Otherwise 0. */
rc = (pParse->nErr>0);
/* Control jumps to here if an error is encountered above, or upon
** successful coding of the SELECT.
*/
select_end:
assert( db->mallocFailed==0 || db->mallocFailed==1 );
pParse->nErr += db->mallocFailed;
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
|
| ︙ | ︙ | |||
138545 138546 138547 138548 138549 138550 138551 |
HashElem *p; /* Loop variable for TEMP triggers */
if( pParse->disableTriggers ){
return 0;
}
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
| < < < < | | | > | > | | | | > > > > | | | | | | | | | > > > > > > | > > > > | 139652 139653 139654 139655 139656 139657 139658 139659 139660 139661 139662 139663 139664 139665 139666 139667 139668 139669 139670 139671 139672 139673 139674 139675 139676 139677 139678 139679 139680 139681 139682 139683 139684 139685 139686 139687 139688 139689 139690 139691 139692 139693 139694 139695 139696 139697 139698 139699 139700 |
HashElem *p; /* Loop variable for TEMP triggers */
if( pParse->disableTriggers ){
return 0;
}
pTmpSchema = pParse->db->aDb[1].pSchema;
p = sqliteHashFirst(&pTmpSchema->trigHash);
pList = pTab->pTrigger;
while( p ){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
&& pTrig->table
&& 0==sqlite3StrICmp(pTrig->table, pTab->zName)
&& pTrig->pTabSchema!=pTmpSchema
){
pTrig->pNext = pList;
pList = pTrig;
}else if( pTrig->op==TK_RETURNING
#ifndef SQLITE_OMIT_VIRTUALTABLE
&& pParse->db->pVtabCtx==0
#endif
){
assert( pParse->bReturning );
assert( &(pParse->u1.pReturning->retTrig) == pTrig );
pTrig->table = pTab->zName;
pTrig->pTabSchema = pTab->pSchema;
pTrig->pNext = pList;
pList = pTrig;
}
p = sqliteHashNext(p);
}
#if 0
if( pList ){
Trigger *pX;
printf("Triggers for %s:", pTab->zName);
for(pX=pList; pX; pX=pX->pNext){
printf(" %s", pX->zName);
}
printf("\n");
fflush(stdout);
}
#endif
return pList;
}
/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions. A Trigger
** structure is generated based on the information available and stored
|
| ︙ | ︙ | |||
138697 138698 138699 138700 138701 138702 138703 |
}
/* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers.
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
| | | | 139816 139817 139818 139819 139820 139821 139822 139823 139824 139825 139826 139827 139828 139829 139830 139831 139832 139833 139834 139835 |
}
/* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers.
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName->a);
goto trigger_orphan_error;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( !IN_RENAME_OBJECT ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int code = SQLITE_CREATE_TRIGGER;
|
| ︙ | ︙ | |||
139099 139100 139101 139102 139103 139104 139105 |
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
if( pTrigger ) break;
}
if( !pTrigger ){
if( !noErr ){
| | | 140218 140219 140220 140221 140222 140223 140224 140225 140226 140227 140228 140229 140230 140231 140232 |
if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
assert( sqlite3SchemaMutexHeld(db, j, 0) );
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
if( pTrigger ) break;
}
if( !pTrigger ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, zDb);
}
pParse->checkSchema = 1;
goto drop_trigger_cleanup;
}
sqlite3DropTriggerPtr(pParse, pTrigger);
|
| ︙ | ︙ | |||
139310 139311 139312 139313 139314 139315 139316 139317 139318 139319 139320 139321 139322 139323 139324 139325 139326 139327 139328 139329 139330 139331 139332 139333 139334 |
pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
}
}else{
sqlite3DbFree(db, zName);
}
return pSrc;
}
/* The input list pList is the list of result set terms from a RETURNING
** clause. The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The arguments to RETURNING */
Table *pTab /* The table being updated */
){
ExprList *pNew = 0;
sqlite3 *db = pParse->db;
int i;
for(i=0; i<pList->nExpr; i++){
Expr *pOldExpr = pList->a[i].pExpr;
| > > > > > > > > > > > > > > > > > > > | > | 140429 140430 140431 140432 140433 140434 140435 140436 140437 140438 140439 140440 140441 140442 140443 140444 140445 140446 140447 140448 140449 140450 140451 140452 140453 140454 140455 140456 140457 140458 140459 140460 140461 140462 140463 140464 140465 140466 140467 140468 140469 140470 140471 140472 140473 140474 140475 140476 140477 140478 140479 140480 140481 |
pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
}
}else{
sqlite3DbFree(db, zName);
}
return pSrc;
}
/*
** Return true if the pExpr term from the RETURNING clause argument
** list is of the form "*". Raise an error if the terms if of the
** form "table.*".
*/
static int isAsteriskTerm(
Parse *pParse, /* Parsing context */
Expr *pTerm /* A term in the RETURNING clause */
){
assert( pTerm!=0 );
if( pTerm->op==TK_ASTERISK ) return 1;
if( pTerm->op!=TK_DOT ) return 0;
assert( pTerm->pRight!=0 );
assert( pTerm->pLeft!=0 );
if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
return 1;
}
/* The input list pList is the list of result set terms from a RETURNING
** clause. The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The arguments to RETURNING */
Table *pTab /* The table being updated */
){
ExprList *pNew = 0;
sqlite3 *db = pParse->db;
int i;
for(i=0; i<pList->nExpr; i++){
Expr *pOldExpr = pList->a[i].pExpr;
if( NEVER(pOldExpr==0) ) continue;
if( isAsteriskTerm(pParse, pOldExpr) ){
int jj;
for(jj=0; jj<pTab->nCol; jj++){
Expr *pNewExpr;
if( IsHiddenColumn(pTab->aCol+jj) ) continue;
pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
if( !db->mallocFailed ){
|
| ︙ | ︙ | |||
139351 139352 139353 139354 139355 139356 139357 |
if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
pItem->eEName = pList->a[i].eEName;
}
}
}
| < < < < < < < < < > > > > > > > > > > > > > > > | | | 140490 140491 140492 140493 140494 140495 140496 140497 140498 140499 140500 140501 140502 140503 140504 140505 140506 140507 140508 140509 140510 140511 140512 140513 140514 140515 140516 140517 140518 140519 140520 140521 140522 140523 140524 140525 140526 140527 140528 140529 140530 140531 140532 140533 140534 140535 140536 140537 140538 140539 140540 140541 140542 140543 140544 140545 140546 140547 140548 140549 140550 140551 140552 140553 140554 140555 140556 140557 140558 140559 140560 140561 140562 140563 140564 140565 140566 140567 |
if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
pItem->eEName = pList->a[i].eEName;
}
}
}
return pNew;
}
/*
** Generate code for the RETURNING trigger. Unlike other triggers
** that invoke a subprogram in the bytecode, the code for RETURNING
** is generated in-line.
*/
static void codeReturningTrigger(
Parse *pParse, /* Parse context */
Trigger *pTrigger, /* The trigger step that defines the RETURNING */
Table *pTab, /* The table to code triggers from */
int regIn /* The first in an array of registers */
){
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
ExprList *pNew;
Returning *pReturning;
Select sSelect;
SrcList sFrom;
assert( v!=0 );
assert( pParse->bReturning );
pReturning = pParse->u1.pReturning;
assert( pTrigger == &(pReturning->retTrig) );
memset(&sSelect, 0, sizeof(sSelect));
memset(&sFrom, 0, sizeof(sFrom));
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
sSelect.pSrc = &sFrom;
sFrom.nSrc = 1;
sFrom.a[0].pTab = pTab;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( db->mallocFailed==0 && pParse->nErr==0 ){
sqlite3GenerateColumnNames(pParse, &sSelect);
}
sqlite3ExprListDelete(db, sSelect.pEList);
pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
if( pNew ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
if( pReturning->nRetCol==0 ){
pReturning->nRetCol = pNew->nExpr;
pReturning->iRetCur = pParse->nTab++;
}
sNC.pParse = pParse;
sNC.uNC.iBaseReg = regIn;
sNC.ncFlags = NC_UBaseReg;
pParse->eTriggerOp = pTrigger->op;
pParse->pTriggerTab = pTab;
if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
int i;
int nCol = pNew->nExpr;
int reg = pParse->nMem+1;
pParse->nMem += nCol+2;
pReturning->iRetReg = reg;
for(i=0; i<nCol; i++){
Expr *pCol = pNew->a[i].pExpr;
sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
}
sqlite3ExprListDelete(db, pNew);
pParse->eTriggerOp = 0;
pParse->pTriggerTab = 0;
}
}
|
| ︙ | ︙ | |||
139611 139612 139613 139614 139615 139616 139617 |
#endif
/* If one was specified, code the WHEN clause. If it evaluates to false
** (or NULL) the sub-vdbe is immediately halted by jumping to the
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
| > | < | 140756 140757 140758 140759 140760 140761 140762 140763 140764 140765 140766 140767 140768 140769 140770 140771 |
#endif
/* If one was specified, code the WHEN clause. If it evaluates to false
** (or NULL) the sub-vdbe is immediately halted by jumping to the
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
if( db->mallocFailed==0
&& SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
){
iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
}
sqlite3ExprDelete(db, pWhen);
}
|
| ︙ | ︙ | |||
140091 140092 140093 140094 140095 140096 140097 140098 140099 140100 140101 140102 140103 140104 |
#endif
pSrc = sqlite3SrcListDup(db, pTabList, 0);
pWhere2 = sqlite3ExprDup(db, pWhere, 0);
assert( pTabList->nSrc>1 );
if( pSrc ){
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
}
if( pPk ){
for(i=0; i<pPk->nKeyCol; i++){
Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);
| > | 141236 141237 141238 141239 141240 141241 141242 141243 141244 141245 141246 141247 141248 141249 141250 |
#endif
pSrc = sqlite3SrcListDup(db, pTabList, 0);
pWhere2 = sqlite3ExprDup(db, pWhere, 0);
assert( pTabList->nSrc>1 );
if( pSrc ){
pSrc->a[0].fg.notCte = 1;
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
}
if( pPk ){
for(i=0; i<pPk->nKeyCol; i++){
Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);
|
| ︙ | ︙ | |||
140120 140121 140122 140123 140124 140125 140126 |
pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( pLimit ){
pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
}
#endif
}
| > | | 141266 141267 141268 141269 141270 141271 141272 141273 141274 141275 141276 141277 141278 141279 141280 141281 |
pList = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( pLimit ){
pGrp = sqlite3ExprListAppend(pParse, 0, sqlite3PExpr(pParse,TK_ROW,0,0));
}
#endif
}
assert( pChanges!=0 || pParse->db->mallocFailed );
if( pChanges ){
for(i=0; i<pChanges->nExpr; i++){
pList = sqlite3ExprListAppend(pParse, pList,
sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
);
}
}
pSelect = sqlite3SelectNew(pParse, pList,
|
| ︙ | ︙ | |||
140670 140671 140672 140673 140674 140675 140676 |
if( addrOnce ){
sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
}
}
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
| > | > > > > | 141817 141818 141819 141820 141821 141822 141823 141824 141825 141826 141827 141828 141829 141830 141831 141832 141833 141834 141835 141836 |
if( addrOnce ){
sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
}
}
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
if( aiCurOnePass[0]!=iDataCur
&& aiCurOnePass[1]!=iDataCur
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
&& !isView
#endif
){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
VdbeCoverage(v);
}
if( eOnePass!=ONEPASS_SINGLE ){
labelContinue = sqlite3VdbeMakeLabel(pParse);
}
|
| ︙ | ︙ | |||
143141 143142 143143 143144 143145 143146 143147 143148 143149 143150 143151 143152 143153 143154 |
return 0;
}
pMod->pEpoTab = pTab;
pTab->nTabRef = 1;
pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 );
pTab->iPKey = -1;
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
if( rc ){
sqlite3ErrorMsg(pParse, "%s", zErr);
sqlite3DbFree(db, zErr);
| > | 144293 144294 144295 144296 144297 144298 144299 144300 144301 144302 144303 144304 144305 144306 144307 |
return 0;
}
pMod->pEpoTab = pTab;
pTab->nTabRef = 1;
pTab->pSchema = db->aDb[0].pSchema;
assert( pTab->nModuleArg==0 );
pTab->iPKey = -1;
pTab->tabFlags |= TF_Eponymous;
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
if( rc ){
sqlite3ErrorMsg(pParse, "%s", zErr);
sqlite3DbFree(db, zErr);
|
| ︙ | ︙ | |||
143557 143558 143559 143560 143561 143562 143563 |
*/
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 */
| | | | 144710 144711 144712 144713 144714 144715 144716 144717 144718 144719 144720 144721 144722 144723 144724 144725 |
*/
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[] */
unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */
u32 opMask; /* Acceptable operators */
int k; /* Resume scanning at this->pWC->a[this->k] */
int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
};
/*
|
| ︙ | ︙ | |||
143867 143868 143869 143870 143871 143872 143873 143874 143875 143876 143877 143878 143879 143880 | #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ #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 */ #endif /* !defined(SQLITE_WHEREINT_H) */ /************** End of whereInt.h ********************************************/ /************** Continuing where we left off in wherecode.c ******************/ #ifndef SQLITE_OMIT_EXPLAIN | > | 145020 145021 145022 145023 145024 145025 145026 145027 145028 145029 145030 145031 145032 145033 145034 | #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ #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 |
| ︙ | ︙ | |||
144001 144002 144003 144004 144005 144006 144007 |
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
| < < < < < < | < | < | 145155 145156 145157 145158 145159 145160 145161 145162 145163 145164 145165 145166 145167 145168 145169 145170 |
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.printfFlags = SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
assert( pLoop->u.btree.pIndex!=0 );
pIdx = pLoop->u.btree.pIndex;
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
|
| ︙ | ︙ | |||
144158 144159 144160 144161 144162 144163 144164 144165 144166 144167 144168 144169 144170 144171 |
&& (pLevel->notReady & pTerm->prereqAll)==0
){
if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
pTerm->wtFlags |= TERM_LIKECOND;
}else{
pTerm->wtFlags |= TERM_CODED;
}
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
pTerm->nChild--;
if( pTerm->nChild!=0 ) break;
nLoop++;
}
| > > > > > > | 145304 145305 145306 145307 145308 145309 145310 145311 145312 145313 145314 145315 145316 145317 145318 145319 145320 145321 145322 145323 |
&& (pLevel->notReady & pTerm->prereqAll)==0
){
if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
pTerm->wtFlags |= TERM_LIKECOND;
}else{
pTerm->wtFlags |= TERM_CODED;
}
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x20000 ){
sqlite3DebugPrintf("DISABLE-");
sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
}
#endif
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
pTerm->nChild--;
if( pTerm->nChild!=0 ) break;
nLoop++;
}
|
| ︙ | ︙ | |||
144475 144476 144477 144478 144479 144480 144481 |
}
}else{
pLevel->u.in.nIn = 0;
}
sqlite3DbFree(pParse->db, aiMap);
#endif
}
| > > > > > > > > > > > > > | > > | 145627 145628 145629 145630 145631 145632 145633 145634 145635 145636 145637 145638 145639 145640 145641 145642 145643 145644 145645 145646 145647 145648 145649 145650 145651 145652 145653 145654 145655 145656 |
}
}else{
pLevel->u.in.nIn = 0;
}
sqlite3DbFree(pParse->db, aiMap);
#endif
}
/* As an optimization, try to disable the WHERE clause term that is
** driving the index as it will always be true. The correct answer is
** obtained regardless, but we might get the answer with fewer CPU cycles
** by omitting the term.
**
** But do not disable the term unless we are certain that the term is
** not a transitive constraint. For an example of where that does not
** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
*/
if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
|| (pTerm->eOperator & WO_EQUIV)==0
){
disableTerm(pLevel, pTerm);
}
return iReg;
}
/*
** Generate code that will evaluate all == and IN constraints for an
** index scan.
**
|
| ︙ | ︙ | |||
144561 144562 144563 144564 144565 144566 144567 144568 144569 144570 144571 144572 144573 144574 |
pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
assert( zAff!=0 || pParse->db->mallocFailed );
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
j = sqlite3VdbeAddOp0(v, OP_Goto);
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
iIdxCur, 0, regBase, nSkip);
| > | 145728 145729 145730 145731 145732 145733 145734 145735 145736 145737 145738 145739 145740 145741 145742 |
pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
assert( zAff!=0 || pParse->db->mallocFailed );
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1);
sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
j = sqlite3VdbeAddOp0(v, OP_Goto);
pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
iIdxCur, 0, regBase, nSkip);
|
| ︙ | ︙ | |||
144595 144596 144597 144598 144599 144600 144601 |
testcase( pTerm->wtFlags & TERM_VIRTUAL );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
regBase = r1;
}else{
| | | | 145763 145764 145765 145766 145767 145768 145769 145770 145771 145772 145773 145774 145775 145776 145777 145778 145779 145780 145781 145782 145783 145784 145785 145786 145787 145788 145789 145790 145791 145792 145793 145794 |
testcase( pTerm->wtFlags & TERM_VIRTUAL );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
regBase = r1;
}else{
sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
}
}
if( pTerm->eOperator & WO_IN ){
if( pTerm->pExpr->flags & EP_xIsSelect ){
/* No affinity ever needs to be (or should be) applied to a value
** from the RHS of an "? IN (SELECT ...)" expression. The
** sqlite3FindInIndex() routine has already ensured that the
** affinity of the comparison has been applied to the value. */
if( zAff ) zAff[j] = SQLITE_AFF_BLOB;
}
}else if( (pTerm->eOperator & WO_ISNULL)==0 ){
Expr *pRight = pTerm->pExpr->pRight;
if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
if( pParse->db->mallocFailed==0 && pParse->nErr==0 ){
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
zAff[j] = SQLITE_AFF_BLOB;
}
}
|
| ︙ | ︙ | |||
144961 144962 144963 144964 144965 144966 144967 |
ExprList *pList = p->x.pList;
assert( nReg<=pList->nExpr );
for(i=0; i<nReg; i++){
sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
}
}
}else{
| | | 146129 146130 146131 146132 146133 146134 146135 146136 146137 146138 146139 146140 146141 146142 146143 |
ExprList *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 );
sqlite3ExprCode(pParse, p, iReg);
}
}
/* An instance of the IdxExprTrans object carries information about a
** mapping from an expression on table columns into a column in an index
** down through the Walker.
|
| ︙ | ︙ | |||
145588 145589 145590 145591 145592 145593 145594 |
pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
}
/* If we are doing a reverse order scan on an ascending index, or
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
| | < < | 146756 146757 146758 146759 146760 146761 146762 146763 146764 146765 146766 146767 146768 146769 146770 |
pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
}
/* If we are doing a reverse order scan on an ascending index, or
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
}
if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
/* In case OP_SeekScan is used, ensure that the index cursor does not
|
| ︙ | ︙ | |||
146011 146012 146013 146014 146015 146016 146017 |
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
if( pAndExpr ){
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlite3PExpr() false, and this
| | > > > > > > | 147177 147178 147179 147180 147181 147182 147183 147184 147185 147186 147187 147188 147189 147190 147191 147192 147193 147194 147195 147196 147197 147198 147199 147200 147201 147202 147203 147204 147205 147206 147207 147208 147209 147210 147211 147212 147213 147214 147215 147216 |
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
if( pAndExpr ){
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlite3PExpr() false, and this
** prevents sqlite3PExpr() from applying the AND short-circuit
** optimization, which we do not want here. */
pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
}
}
/* Run a separate WHERE clause for each term of the OR clause. After
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pOrExpr, EP_FromJoin)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDelete);
continue;
}
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
}
/* Loop through table entries that match term pOrTerm. */
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
|
| ︙ | ︙ | |||
146145 146146 146147 146148 146149 146150 146151 146152 146153 146154 146155 146156 146157 146158 |
pWInfo->bDeferredSeek = 1;
}
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
}
}
ExplainQueryPlanPop(pParse);
pLevel->u.pCovidx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
| > | 147317 147318 147319 147320 147321 147322 147323 147324 147325 147326 147327 147328 147329 147330 147331 |
pWInfo->bDeferredSeek = 1;
}
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
pLevel->u.pCovidx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
|
| ︙ | ︙ | |||
146309 146310 146311 146312 146313 146314 146315 146316 146317 146318 146319 146320 146321 146322 |
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IS );
testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint"));
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
}
/* 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);
| > | 147482 147483 147484 147485 147486 147487 147488 147489 147490 147491 147492 147493 147494 147495 147496 |
testcase( pAlt->eOperator & WO_EQ );
testcase( pAlt->eOperator & WO_IS );
testcase( pAlt->eOperator & WO_IN );
VdbeModuleComment((v, "begin transitive constraint"));
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
pAlt->wtFlags |= TERM_CODED;
}
/* 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);
|
| ︙ | ︙ | |||
146861 146862 146863 146864 146865 146866 146867 146868 146869 146870 146871 146872 146873 146874 |
){
u16 eOp = pOne->eOperator | pTwo->eOperator;
sqlite3 *db; /* Database connection (for malloc) */
Expr *pNew; /* New virtual expression */
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
| > | 148035 148036 148037 148038 148039 148040 148041 148042 148043 148044 148045 148046 148047 148048 148049 |
){
u16 eOp = pOne->eOperator | pTwo->eOperator;
sqlite3 *db; /* Database connection (for malloc) */
Expr *pNew; /* New virtual expression */
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
&& (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
|
| ︙ | ︙ | |||
147221 147222 147223 147224 147225 147226 147227 |
int idxNew;
transferJoinMarkings(pNew, pExpr);
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
pNew->x.pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
| | | 148396 148397 148398 148399 148400 148401 148402 148403 148404 148405 148406 148407 148408 148409 148410 |
int idxNew;
transferJoinMarkings(pNew, pExpr);
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
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{
sqlite3ExprListDelete(db, pList);
}
}
}
}
|
| ︙ | ︙ | |||
147345 147346 147347 147348 147349 147350 147351 147352 147353 147354 147355 147356 147357 147358 147359 147360 147361 147362 147363 |
** 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;
return 1;
}
if( mPrereq==0 ) return 0; /* No table references */
if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
| > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 148520 148521 148522 148523 148524 148525 148526 148527 148528 148529 148530 148531 148532 148533 148534 148535 148536 148537 148538 148539 148540 148541 148542 148543 148544 148545 148546 |
** 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;
return 1;
}
if( mPrereq==0 ) return 0; /* No table references */
if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
|
| ︙ | ︙ | |||
147725 147726 147727 147728 147729 147730 147731 147732 147733 147734 147735 147736 147737 147738 |
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)
){
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
assert( pTerm->u.x.iField==0 );
if( pTerm->leftCursor>=0 ){
int idxNew;
| > | 148632 148633 148634 148635 148636 148637 148638 148639 148640 148641 148642 148643 148644 148645 148646 |
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)
){
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
assert( pTerm->u.x.iField==0 );
if( pTerm->leftCursor>=0 ){
int idxNew;
|
| ︙ | ︙ | |||
147817 147818 147819 147820 147821 147822 147823 |
*/
else if( pExpr->op==TK_OR ){
assert( pWC->op==TK_AND );
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
| < < < < < < < < < < | 148725 148726 148727 148728 148729 148730 148731 148732 148733 148734 148735 148736 148737 148738 |
*/
else if( pExpr->op==TK_OR ){
assert( pWC->op==TK_AND );
exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
/* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
**
** The virtual term must be tagged with TERM_VNULL.
*/
else if( pExpr->op==TK_NOTNULL ){
|
| ︙ | ︙ | |||
148513 148514 148515 148516 148517 148518 148519 |
/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch. Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlite3ExprSkipCollateAndLikely(p->pRight);
| | > > | 149411 149412 149413 149414 149415 149416 149417 149418 149419 149420 149421 149422 149423 149424 149425 149426 149427 |
/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch. Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlite3ExprSkipCollateAndLikely(p->pRight);
if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return p;
}
return 0;
}
/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
|
| ︙ | ︙ | |||
148588 148589 148590 148591 148592 148593 148594 148595 148596 148597 148598 148599 148600 148601 |
&& pX->iColumn==pScan->aiColumn[0]
){
testcase( pTerm->eOperator & WO_IS );
continue;
}
pScan->pWC = pWC;
pScan->k = k+1;
return pTerm;
}
}
}
pWC = pWC->pOuter;
k = 0;
}while( pWC!=0 );
| > > > > > > > > > > > > | 149488 149489 149490 149491 149492 149493 149494 149495 149496 149497 149498 149499 149500 149501 149502 149503 149504 149505 149506 149507 149508 149509 149510 149511 149512 149513 |
&& pX->iColumn==pScan->aiColumn[0]
){
testcase( pTerm->eOperator & WO_IS );
continue;
}
pScan->pWC = pWC;
pScan->k = k+1;
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace & 0x20000 ){
int ii;
sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
pTerm, pScan->nEquiv);
for(ii=0; ii<pScan->nEquiv; ii++){
sqlite3DebugPrintf(" {%d:%d}",
pScan->aiCur[ii], pScan->aiColumn[ii]);
}
sqlite3DebugPrintf("\n");
}
#endif
return pTerm;
}
}
}
pWC = pWC->pOuter;
k = 0;
}while( pWC!=0 );
|
| ︙ | ︙ | |||
148744 148745 148746 148747 148748 148749 148750 |
){
int i;
const char *zColl = pIdx->azColl[iCol];
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( ALWAYS(p!=0)
| | | 149656 149657 149658 149659 149660 149661 149662 149663 149664 149665 149666 149667 149668 149669 149670 |
){
int i;
const char *zColl = pIdx->azColl[iCol];
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( ALWAYS(p!=0)
&& (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
return i;
}
|
| ︙ | ︙ | |||
148809 148810 148811 148812 148813 148814 148815 |
/* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
** current SELECT is a correlated sub-query.
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
| > | > | 149721 149722 149723 149724 149725 149726 149727 149728 149729 149730 149731 149732 149733 149734 149735 149736 149737 149738 149739 149740 149741 149742 149743 149744 149745 149746 149747 149748 149749 149750 149751 149752 149753 149754 |
/* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
** current SELECT is a correlated sub-query.
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
if( p->iTable==iBase && p->iColumn<0 ) return 1;
}
/* Loop through all indices on the table, checking each to see if it makes
** the DISTINCT qualifier redundant. It does so if:
**
** 1. The index is itself UNIQUE, and
**
** 2. All of the columns in the index are either part of the pDistinct
** list, or else the WHERE clause contains a term of the form "col=X",
** where X is a constant value. The collation sequences of the
** comparison and select-list expressions must match those of the index.
**
** 3. All of those index columns for which the WHERE clause does not
** contain a "col=X" term are subject to a NOT NULL constraint.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !IsUniqueIndex(pIdx) ) continue;
if( pIdx->pPartIdxWhere ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
if( indexColumnNotNull(pIdx, i)==0 ) break;
}
}
if( i==pIdx->nKeyCol ){
|
| ︙ | ︙ | |||
148881 148882 148883 148884 148885 148886 148887 |
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
| < | | < > > < > | 149795 149796 149797 149798 149799 149800 149801 149802 149803 149804 149805 149806 149807 149808 149809 149810 149811 149812 149813 149814 149815 149816 |
if( pOp->p1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
pOp->opcode = OP_Sequence;
pOp->p1 = iAutoidxCur;
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
pOp->p3 = 0;
}
#endif
}
}
}
/*
** Two routines for printing the content of an sqlite3_index_info
** structure. Used for testing and debugging only. If neither
|
| ︙ | ︙ | |||
149053 149054 149055 149056 149057 149058 149059 |
goto end_auto_index_create;
}
pLoop->aLTerm[nKeyCol++] = pTerm;
idxCols |= cMask;
}
}
}
| | | 149967 149968 149969 149970 149971 149972 149973 149974 149975 149976 149977 149978 149979 149980 149981 |
goto end_auto_index_create;
}
pLoop->aLTerm[nKeyCol++] = pTerm;
idxCols |= cMask;
}
}
}
assert( nKeyCol>0 || pParse->db->mallocFailed );
pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
| WHERE_AUTO_INDEX;
/* Count the number of additional columns needed to create a
** covering index. A "covering index" is an index that contains all
** columns that are needed by the query. With a covering index, the
|
| ︙ | ︙ | |||
150190 150191 150192 150193 150194 150195 150196 |
/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
whereLoopClearUnion(db, pTo);
if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
| | | 151104 151105 151106 151107 151108 151109 151110 151111 151112 151113 151114 151115 151116 151117 151118 |
/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
whereLoopClearUnion(db, pTo);
if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
memset(pTo, 0, WHERE_LOOP_XFER_SZ);
return SQLITE_NOMEM_BKPT;
}
memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
pFrom->u.vtab.needFree = 0;
}else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
|
| ︙ | ︙ | |||
150232 150233 150234 150235 150236 150237 150238 150239 150240 150241 150242 150243 150244 150245 |
WhereLoop *p = pWInfo->pLoops;
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
assert( pWInfo->pExprMods==0 );
sqlite3DbFreeNN(db, pWInfo);
}
/*
** Return TRUE if all of the following are true:
**
** (1) X has the same or lower cost that Y
** (2) X uses fewer WHERE clause terms than Y
** (3) Every WHERE clause term used by X is also used by Y
| > > > > > > > > > > > | 151146 151147 151148 151149 151150 151151 151152 151153 151154 151155 151156 151157 151158 151159 151160 151161 151162 151163 151164 151165 151166 151167 151168 151169 151170 |
WhereLoop *p = pWInfo->pLoops;
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
assert( pWInfo->pExprMods==0 );
sqlite3DbFreeNN(db, pWInfo);
}
/* Undo all Expr node modifications
*/
static void whereUndoExprMods(WhereInfo *pWInfo){
while( pWInfo->pExprMods ){
WhereExprMod *p = pWInfo->pExprMods;
pWInfo->pExprMods = p->pNext;
memcpy(p->pExpr, &p->orig, sizeof(p->orig));
sqlite3DbFree(pWInfo->pParse->db, p);
}
}
/*
** Return TRUE if all of the following are true:
**
** (1) X has the same or lower cost that Y
** (2) X uses fewer WHERE clause terms than Y
** (3) Every WHERE clause term used by X is also used by Y
|
| ︙ | ︙ | |||
150738 150739 150740 150741 150742 150743 150744 150745 150746 150747 150748 150749 150750 150751 |
}else{
assert( pNew->u.btree.nBtm==0 );
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
}
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEq<pProbe->nColumn );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
saved_nTop = pNew->u.btree.nTop;
saved_nSkip = pNew->nSkip;
saved_nLTerm = pNew->nLTerm;
saved_wsFlags = pNew->wsFlags;
| > > | 151663 151664 151665 151666 151667 151668 151669 151670 151671 151672 151673 151674 151675 151676 151677 151678 |
}else{
assert( pNew->u.btree.nBtm==0 );
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
}
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEq<pProbe->nColumn );
assert( pNew->u.btree.nEq<pProbe->nKeyCol
|| pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
saved_nTop = pNew->u.btree.nTop;
saved_nSkip = pNew->nSkip;
saved_nLTerm = pNew->nLTerm;
saved_wsFlags = pNew->wsFlags;
|
| ︙ | ︙ | |||
150820 150821 150822 150823 150824 150825 150826 |
if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
}
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
if( pProbe->hasStat1 && rLogSize>=10 ){
| | | 151747 151748 151749 151750 151751 151752 151753 151754 151755 151756 151757 151758 151759 151760 151761 |
if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
}
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
if( pProbe->hasStat1 && rLogSize>=10 ){
LogEst M, logK, x;
/* Let:
** N = the total number of rows in the table
** K = the number of entries on the RHS of the IN operator
** M = the number of rows in the table that match terms to the
** to the left in the same index. If the IN operator is on
** the left-most index column, M==N.
**
|
| ︙ | ︙ | |||
150843 150844 150845 150846 150847 150848 150849 |
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
** the index. Do not bother with this optimization on very small
** tables (less than 2 rows) as it is pointless in that case.
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
| | | > | > | > > > > > | > | > > | 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 151799 151800 151801 151802 151803 151804 151805 151806 151807 151808 151809 151810 151811 151812 151813 151814 151815 151816 151817 151818 151819 151820 151821 |
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
** the index. Do not bother with this optimization on very small
** tables (less than 2 rows) as it is pointless in that case.
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
/* TUNING v----- 10 to bias toward indexed IN */
x = M + logK + 10 - (nIn + rLogSize);
if( x>=0 ){
WHERETRACE(0x40,
("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d) "
"prefers indexed lookup\n",
saved_nEq, M, logK, nIn, rLogSize, x));
}else if( nInMul<2 && OptimizationEnabled(db, SQLITE_SeekScan) ){
WHERETRACE(0x40,
("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
" nInMul=%d) prefers skip-scan\n",
saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
" nInMul=%d) prefers normal scan\n",
saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
continue;
}
}
pNew->wsFlags |= WHERE_COLUMN_IN;
}else if( eOp & (WO_EQ|WO_IS) ){
int iCol = pProbe->aiColumn[saved_nEq];
pNew->wsFlags |= WHERE_COLUMN_EQ;
assert( saved_nEq==pNew->u.btree.nEq );
if( iCol==XN_ROWID
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
){
if( iCol==XN_ROWID || pProbe->uniqNotNull
|| (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
){
pNew->wsFlags |= WHERE_ONEROW;
}else{
pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
}else if( eOp & WO_ISNULL ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
}else if( eOp & (WO_GT|WO_GE) ){
testcase( eOp & WO_GT );
testcase( eOp & WO_GE );
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
pNew->u.btree.nBtm = whereRangeVectorLen(
|
| ︙ | ︙ | |||
151014 151015 151016 151017 151018 151019 151020 151021 151022 151023 151024 151025 151026 151027 |
pNew->nOut = saved_nOut;
}else{
pNew->nOut = nOutUnadjusted;
}
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT4
pBuilder->nRecValid = nRecValid;
#endif
| > > | 151951 151952 151953 151954 151955 151956 151957 151958 151959 151960 151961 151962 151963 151964 151965 151966 |
pNew->nOut = saved_nOut;
}else{
pNew->nOut = nOutUnadjusted;
}
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
&& (pNew->u.btree.nEq<pProbe->nKeyCol ||
pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT4
pBuilder->nRecValid = nRecValid;
#endif
|
| ︙ | ︙ | |||
151135 151136 151137 151138 151139 151140 151141 151142 151143 151144 151145 151146 151147 151148 |
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
&& (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
){
return 1;
}
}
return 0;
}
| > | 152074 152075 152076 152077 152078 152079 152080 152081 152082 152083 152084 152085 152086 152087 152088 |
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
&& (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
}
}
return 0;
}
|
| ︙ | ︙ | |||
151845 151846 151847 151848 151849 151850 151851 |
#endif
{
rc = whereLoopAddBtree(&sSubBuild, mPrereq);
}
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
| | > > | 152785 152786 152787 152788 152789 152790 152791 152792 152793 152794 152795 152796 152797 152798 152799 152800 152801 |
#endif
{
rc = whereLoopAddBtree(&sSubBuild, mPrereq);
}
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0
|| rc==SQLITE_NOMEM );
testcase( rc==SQLITE_NOMEM && sCur.n>0 );
testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
break;
}else if( once ){
whereOrMove(&sSum, &sCur);
once = 0;
|
| ︙ | ︙ | |||
152074 152075 152076 152077 152078 152079 152080 |
** clause of the form X IS NULL or X=? that reference only outer
** loops.
*/
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( NEVER(pOBExpr==0) ) continue;
| | | 153016 153017 153018 153019 153020 153021 153022 153023 153024 153025 153026 153027 153028 153029 153030 |
** clause of the form X IS NULL or X=? that reference only outer
** loops.
*/
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( NEVER(pOBExpr==0) ) continue;
if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, eqOpMask, 0);
if( pTerm==0 ) continue;
if( pTerm->eOperator==WO_IN ){
/* IN terms are only valid for sorting in the ORDER BY LIMIT
** optimization, and then only if they are actually used
|
| ︙ | ︙ | |||
152114 152115 152116 152117 152118 152119 152120 152121 152122 152123 152124 152125 152126 152127 |
return 0;
}else{
nKeyCol = pIndex->nKeyCol;
nColumn = pIndex->nColumn;
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
/* Loop through all columns of the index and deal with the ones
** that are not constrained by == or IN.
*/
| > > > > | 153056 153057 153058 153059 153060 153061 153062 153063 153064 153065 153066 153067 153068 153069 153070 153071 153072 153073 |
return 0;
}else{
nKeyCol = pIndex->nKeyCol;
nColumn = pIndex->nColumn;
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
/* All relevant terms of the index must also be non-NULL in order
** for isOrderDistinct to be true. So the isOrderDistint value
** computed here might be a false positive. Corrections will be
** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
/* Loop through all columns of the index and deal with the ones
** that are not constrained by == or IN.
*/
|
| ︙ | ︙ | |||
152181 152182 152183 152184 152185 152186 152187 |
if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
}else{
iColumn = XN_ROWID;
revIdx = 0;
}
/* An unconstrained column that might be NULL means that this
| | | | | | | | > > > > | | 153127 153128 153129 153130 153131 153132 153133 153134 153135 153136 153137 153138 153139 153140 153141 153142 153143 153144 153145 153146 153147 153148 153149 153150 153151 153152 153153 153154 153155 153156 153157 153158 153159 153160 153161 153162 153163 153164 153165 153166 153167 |
if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
}else{
iColumn = XN_ROWID;
revIdx = 0;
}
/* An unconstrained column that might be NULL means that this
** WhereLoop is not well-ordered. tag-20210426-1
*/
if( isOrderDistinct ){
if( iColumn>=0
&& j>=pLoop->u.btree.nEq
&& pIndex->pTable->aCol[iColumn].notNull==0
){
isOrderDistinct = 0;
}
if( iColumn==XN_EXPR ){
isOrderDistinct = 0;
}
}
/* Find the ORDER BY term that corresponds to the j-th column
** of the index and mark that ORDER BY term off
*/
isMatch = 0;
for(i=0; bOnce && i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
continue;
}
|
| ︙ | ︙ | |||
152372 152373 152374 152375 152376 152377 152378 |
** rows, so fudge it downwards a bit.
*/
if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
nRow = pWInfo->iLimit;
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
| | | 153322 153323 153324 153325 153326 153327 153328 153329 153330 153331 153332 153333 153334 153335 153336 |
** rows, so fudge it downwards a bit.
*/
if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
nRow = pWInfo->iLimit;
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
if( nRow>10 ){ nRow -= 10; assert( 10==sqlite3LogEst(2) ); }
}
rSortCost += estLog(nRow);
return rSortCost;
}
/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
| ︙ | ︙ | |||
153304 153305 153306 153307 153308 153309 153310 | ** ** SELECT DISTINCT v1, v3 FROM t1 ** LEFT JOIN t2 ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) */ notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 | | > | 154254 154255 154256 154257 154258 154259 154260 154261 154262 154263 154264 154265 154266 154267 154268 154269 |
**
** SELECT DISTINCT v1, v3 FROM t1
** LEFT JOIN t2
** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
*/
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)
){
int i;
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
if( sWLB.pOrderBy ){
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
}
|
| ︙ | ︙ | |||
153563 153564 153565 153566 153567 153568 153569 153570 153571 153572 153573 153574 153575 153576 |
VdbeModuleComment((v, "Begin WHERE-core"));
pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
return pWInfo;
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
}
return 0;
}
/*
| > > | 154514 154515 154516 154517 154518 154519 154520 154521 154522 154523 154524 154525 154526 154527 154528 154529 |
VdbeModuleComment((v, "Begin WHERE-core"));
pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
return pWInfo;
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
testcase( pWInfo->pExprMods!=0 );
whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
}
return 0;
}
/*
|
| ︙ | ︙ | |||
153659 153660 153661 153662 153663 153664 153665 153666 153667 153668 153669 153670 153671 153672 |
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && 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--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
int bEarlyOut =
(pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
&& (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
| > > | 154612 154613 154614 154615 154616 154617 154618 154619 154620 154621 154622 154623 154624 154625 154626 154627 |
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && 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);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
int bEarlyOut =
(pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
&& (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
|
| ︙ | ︙ | |||
153683 153684 153685 153686 153687 153688 153689 153690 153691 153692 153693 153694 153695 153696 |
VdbeCoverage(v);
}
if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
| > > > > > | 154638 154639 154640 154641 154642 154643 154644 154645 154646 154647 154648 154649 154650 154651 154652 154653 154654 154655 154656 |
VdbeCoverage(v);
}
if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
/* Retarget the OP_IsNull against the left operand of IN so
** it jumps past the OP_IfNoHope. This is because the
** OP_IsNull also bypasses the OP_Affinity opcode that is
** required by OP_IfNoHope. */
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
|
| ︙ | ︙ | |||
153817 153818 153819 153820 153821 153822 153823 |
pOp = sqlite3VdbeGetOp(v, k - 1);
assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
| | | 154777 154778 154779 154780 154781 154782 154783 154784 154785 154786 154787 154788 154789 154790 154791 |
pOp = sqlite3VdbeGetOp(v, k - 1);
assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
assert( pOp<=pLastOp );
do{
if( pOp->p1!=pLevel->iTabCur ){
/* no-op */
}else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|| pOp->opcode==OP_Offset
#endif
|
| ︙ | ︙ | |||
153862 153863 153864 153865 153866 153867 153868 |
}while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
}
}
| < < < < < < < < > | 154822 154823 154824 154825 154826 154827 154828 154829 154830 154831 154832 154833 154834 154835 154836 154837 154838 |
}while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
}
}
/* Final cleanup
*/
if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
return;
}
/************** End of where.c ***********************************************/
/************** Begin file window.c ******************************************/
|
| ︙ | ︙ | |||
154669 154670 154671 154672 154673 154674 154675 154676 154677 154678 154679 154680 154681 154682 |
}
}
/* no break */ deliberate_fall_through
case TK_AGG_FUNCTION:
case TK_COLUMN: {
int iCol = -1;
if( p->pSub ){
int i;
for(i=0; i<p->pSub->nExpr; i++){
if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
iCol = i;
break;
}
| > | 155622 155623 155624 155625 155626 155627 155628 155629 155630 155631 155632 155633 155634 155635 155636 |
}
}
/* no break */ deliberate_fall_through
case TK_AGG_FUNCTION:
case TK_COLUMN: {
int iCol = -1;
if( pParse->db->mallocFailed ) return WRC_Abort;
if( p->pSub ){
int i;
for(i=0; i<p->pSub->nExpr; i++){
if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
iCol = i;
break;
}
|
| ︙ | ︙ | |||
154778 154779 154780 154781 154782 154783 154784 |
ExprList *pAppend, /* List of values to append. Might be NULL */
int bIntToNull
){
if( pAppend ){
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; i<pAppend->nExpr; i++){
| > | > > > > | | 155732 155733 155734 155735 155736 155737 155738 155739 155740 155741 155742 155743 155744 155745 155746 155747 155748 155749 155750 155751 155752 155753 |
ExprList *pAppend, /* List of values to append. Might be NULL */
int bIntToNull
){
if( pAppend ){
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; i<pAppend->nExpr; i++){
sqlite3 *db = pParse->db;
Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDup);
break;
}
if( bIntToNull ){
int iDummy;
Expr *pSub;
for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
assert( pSub );
}
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
pSub->op = TK_NULL;
|
| ︙ | ︙ | |||
154815 154816 154817 154818 154819 154820 154821 154822 154823 154824 154825 154826 154827 154828 154829 154830 154831 |
if( pExpr->op==TK_AGG_FUNCTION
&& pExpr->op2>=pWalker->walkerDepth
){
pExpr->op2++;
}
return WRC_Continue;
}
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
*/
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
| > > > > > > > > | | 155774 155775 155776 155777 155778 155779 155780 155781 155782 155783 155784 155785 155786 155787 155788 155789 155790 155791 155792 155793 155794 155795 155796 155797 155798 155799 155800 155801 155802 155803 155804 155805 155806 |
if( pExpr->op==TK_AGG_FUNCTION
&& pExpr->op2>=pWalker->walkerDepth
){
pExpr->op2++;
}
return WRC_Continue;
}
static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
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
** any SQL window functions, this function is a no-op. Otherwise, it
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
*/
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
if( p->pWin && p->pPrior==0 && ALWAYS((p->selFlags & SF_WinRewrite)==0) ){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
SrcList *pSrc = p->pSrc;
Expr *pWhere = p->pWhere;
ExprList *pGroupBy = p->pGroupBy;
Expr *pHaving = p->pHaving;
|
| ︙ | ︙ | |||
154849 154850 154851 154852 154853 154854 154855 154856 154857 154858 154859 154860 154861 154862 |
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
p->pSrc = 0;
p->pWhere = 0;
p->pGroupBy = 0;
p->pHaving = 0;
p->selFlags &= ~SF_Aggregate;
p->selFlags |= SF_WinRewrite;
| > > > > > | 155816 155817 155818 155819 155820 155821 155822 155823 155824 155825 155826 155827 155828 155829 155830 155831 155832 155833 155834 |
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlite3WalkSelect(&w, p);
if( (p->selFlags & SF_Aggregate)==0 ){
w.xExprCallback = disallowAggregatesInOrderByCb;
w.xSelectCallback = 0;
sqlite3WalkExprList(&w, p->pOrderBy);
}
p->pSrc = 0;
p->pWhere = 0;
p->pGroupBy = 0;
p->pHaving = 0;
p->selFlags &= ~SF_Aggregate;
p->selFlags |= SF_WinRewrite;
|
| ︙ | ︙ | |||
155350 155351 155352 155353 155354 155355 155356 155357 155358 155359 155360 155361 155362 155363 |
VdbeCoverage(v);
assert( eCond==0 || eCond==1 || eCond==2 );
VdbeCoverageIf(v, eCond==0);
VdbeCoverageIf(v, eCond==1);
VdbeCoverageIf(v, eCond==2);
}
sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */
VdbeCoverageNeverNullIf(v, eCond==4); /* the OP_Ge */
sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
| > | 156322 156323 156324 156325 156326 156327 156328 156329 156330 156331 156332 156333 156334 156335 156336 |
VdbeCoverage(v);
assert( eCond==0 || eCond==1 || eCond==2 );
VdbeCoverageIf(v, eCond==0);
VdbeCoverageIf(v, eCond==1);
VdbeCoverageIf(v, eCond==2);
}
sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */
VdbeCoverageNeverNullIf(v, eCond==4); /* the OP_Ge */
sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
|
| ︙ | ︙ | |||
155444 155445 155446 155447 155448 155449 155450 155451 155452 155453 155454 155455 155456 155457 | Parse *pParse; /* Parse context */ Window *pMWin; /* First in list of functions being processed */ Vdbe *pVdbe; /* VDBE object */ int addrGosub; /* OP_Gosub to this address to return one row */ int regGosub; /* Register used with OP_Gosub(addrGosub) */ int regArg; /* First in array of accumulator registers */ int eDelete; /* See above */ WindowCsrAndReg start; WindowCsrAndReg current; WindowCsrAndReg end; }; /* | > | 156417 156418 156419 156420 156421 156422 156423 156424 156425 156426 156427 156428 156429 156430 156431 | Parse *pParse; /* Parse context */ Window *pMWin; /* First in list of functions being processed */ Vdbe *pVdbe; /* VDBE object */ int addrGosub; /* OP_Gosub to this address to return one row */ int regGosub; /* Register used with OP_Gosub(addrGosub) */ int regArg; /* First in array of accumulator registers */ int eDelete; /* See above */ int regRowid; WindowCsrAndReg start; WindowCsrAndReg current; WindowCsrAndReg end; }; /* |
| ︙ | ︙ | |||
155560 155561 155562 155563 155564 155565 155566 |
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 ){
| | | | | | 156534 156535 156536 156537 156538 156539 156540 156541 156542 156543 156544 156545 156546 156547 156548 156549 156550 156551 156552 156553 156554 156555 156556 |
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;
|
| ︙ | ︙ | |||
155927 155928 155929 155930 155931 155932 155933 | ** subtracted. And the comparison operator is inverted to - ">=" becomes "<=", ** ">" becomes "<", and so on. So, with DESC sort order, if the argument op ** is OP_Ge, the generated code is equivalent to: ** ** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl; ** ** A special type of arithmetic is used such that if csr1.peerVal is not | | > > > > > < < < < < < < < < < < < < < < < < < < < < < < | 156901 156902 156903 156904 156905 156906 156907 156908 156909 156910 156911 156912 156913 156914 156915 156916 156917 156918 156919 156920 156921 156922 156923 156924 156925 156926 156927 156928 156929 156930 156931 156932 156933 156934 156935 156936 156937 156938 156939 156940 156941 156942 156943 156944 156945 156946 156947 156948 156949 156950 156951 156952 156953 156954 156955 156956 |
** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
WindowCodeArg *p,
int op, /* OP_Ge, OP_Gt, or OP_Le */
int csr1, /* Cursor number for cursor 1 */
int regVal, /* Register containing non-negative number */
int csr2, /* Cursor number for cursor 2 */
int lbl /* Jump destination if condition is true */
){
Parse *pParse = p->pParse;
Vdbe *v = sqlite3GetVdbe(pParse);
ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */
int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */
int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
int addrDone = sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */
CollSeq *pColl;
/* Read the peer-value from each cursor into a register */
windowReadPeerValues(p, csr1, reg1);
windowReadPeerValues(p, csr2, reg2);
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
switch( op ){
case OP_Ge: op = OP_Le; break;
case OP_Gt: op = OP_Lt; break;
default: assert( op==OP_Le ); op = OP_Ge; break;
}
arith = OP_Subtract;
}
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
** (and adding that capability causes a performance regression), so
** instead if the BIGNULL flag is set then cases where either reg1 or
** reg2 are NULL are handled separately in the following block. The code
** generated is equivalent to:
|
| ︙ | ︙ | |||
156023 156024 156025 156026 156027 156028 156029 |
break;
case OP_Le:
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
VdbeCoverage(v);
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
| | | > > > > > > > > > > > > > > > > > > > > > > > | 156979 156980 156981 156982 156983 156984 156985 156986 156987 156988 156989 156990 156991 156992 156993 156994 156995 156996 156997 156998 156999 157000 157001 157002 157003 157004 157005 157006 157007 157008 157009 157010 157011 157012 157013 157014 157015 157016 157017 157018 157019 157020 157021 157022 157023 157024 157025 157026 157027 157028 157029 157030 157031 157032 |
break;
case OP_Le:
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
VdbeCoverage(v);
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
if( op==OP_Gt || op==OP_Ge ){
sqlite3VdbeChangeP2(v, -1, addrDone);
}
}
/* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
** This block adds (or subtracts for DESC) the numeric value in regVal
** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
** then leave reg1 as it is. In pseudo-code, this is implemented as:
**
** if( reg1>='' ) goto addrGe;
** reg1 = reg1 +/- regVal
** addrGe:
**
** Since all strings and blobs are greater-than-or-equal-to an empty string,
** the add/subtract is skipped for these, as required. If reg1 is a NULL,
** then the arithmetic is performed, but since adding or subtracting from
** NULL is always NULL anyway, this case is handled as required too. */
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
VdbeCoverage(v);
if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
sqlite3VdbeJumpHere(v, addrGe);
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
sqlite3VdbeResolveLabel(v, addrDone);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
sqlite3ReleaseTempReg(pParse, reg1);
|
| ︙ | ︙ | |||
156115 156116 156117 156118 156119 156120 156121 |
windowAggFinal(p, 0);
}
addrContinue = sqlite3VdbeCurrentAddr(v);
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
| | > > | > | | | | > > > > > | 157094 157095 157096 157097 157098 157099 157100 157101 157102 157103 157104 157105 157106 157107 157108 157109 157110 157111 157112 157113 157114 157115 157116 157117 157118 157119 157120 157121 157122 157123 157124 157125 |
windowAggFinal(p, 0);
}
addrContinue = sqlite3VdbeCurrentAddr(v);
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
** temporary table. It otherwise might, if (a>b). Also ensure that,
** if the input cursor is still finding new rows, that the end
** cursor does not go past it to EOF. */
if( pMWin->eStart==pMWin->eEnd && regCountdown
&& pMWin->eFrmType==TK_RANGE
){
int regRowid1 = sqlite3GetTempReg(pParse);
int regRowid2 = sqlite3GetTempReg(pParse);
if( op==WINDOW_AGGINVERSE ){
sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
VdbeCoverage(v);
}else if( p->regRowid ){
sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
VdbeCoverageNeverNull(v);
}
sqlite3ReleaseTempReg(pParse, regRowid1);
sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
}
switch( op ){
case WINDOW_RETURN_ROW:
|
| ︙ | ︙ | |||
156621 156622 156623 156624 156625 156626 156627 | int iInput; /* To iterate through sub cols */ int addrNe; /* Address of OP_Ne */ int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ int addrInteger = 0; /* Address of OP_Integer */ int addrEmpty; /* Address of OP_Rewind in flush: */ int regNew; /* Array of registers holding new input row */ int regRecord; /* regNew array in record form */ | < | 157608 157609 157610 157611 157612 157613 157614 157615 157616 157617 157618 157619 157620 157621 | int iInput; /* To iterate through sub cols */ int addrNe; /* Address of OP_Ne */ int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ int addrInteger = 0; /* Address of OP_Integer */ int addrEmpty; /* Address of OP_Rewind in flush: */ int regNew; /* Array of registers holding new input row */ int regRecord; /* regNew array in record form */ int regNewPeer = 0; /* Peer values for new row (part of regNew) */ int regPeer = 0; /* Peer values for current row */ int regFlushPart = 0; /* Register for "Gosub flush_partition" */ WindowCodeArg s; /* Context object for sub-routines */ int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */ int regStart = 0; /* Value of <expr> PRECEDING */ int regEnd = 0; /* Value of <expr> FOLLOWING */ |
| ︙ | ︙ | |||
156693 156694 156695 156696 156697 156698 156699 | /* Allocate registers for the array of values from the sub-query, the ** samve values in record form, and the rowid used to insert said record ** into the ephemeral table. */ regNew = pParse->nMem+1; pParse->nMem += nInput; regRecord = ++pParse->nMem; | | | 157679 157680 157681 157682 157683 157684 157685 157686 157687 157688 157689 157690 157691 157692 157693 |
/* Allocate registers for the array of values from the sub-query, the
** samve values in record form, and the rowid used to insert said record
** into the ephemeral table. */
regNew = pParse->nMem+1;
pParse->nMem += nInput;
regRecord = ++pParse->nMem;
s.regRowid = ++pParse->nMem;
/* If the window frame contains an "<expr> PRECEDING" or "<expr> FOLLOWING"
** clause, allocate registers to store the results of evaluating each
** <expr>. */
if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){
regStart = ++pParse->nMem;
}
|
| ︙ | ︙ | |||
156749 156750 156751 156752 156753 156754 156755 |
VdbeCoverageEqNe(v);
addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart);
VdbeComment((v, "call flush_partition"));
sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
}
/* Insert the new row into the ephemeral table */
| | | | | 157735 157736 157737 157738 157739 157740 157741 157742 157743 157744 157745 157746 157747 157748 157749 157750 157751 |
VdbeCoverageEqNe(v);
addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart);
VdbeComment((v, "call flush_partition"));
sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
}
/* Insert the new row into the ephemeral table */
sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
VdbeCoverageNeverNull(v);
/* This block is run for the first row of each partition */
s.regArg = windowInitAccum(pParse, pMWin);
if( regStart ){
sqlite3ExprCode(pParse, pMWin->pStart, regStart);
|
| ︙ | ︙ | |||
156869 156870 156871 156872 156873 156874 156875 156876 156877 156878 156879 156880 156881 156882 |
/* Fall through */
if( pMWin->pPartition ){
addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
VdbeCoverage(v);
if( pMWin->eEnd==TK_PRECEDING ){
int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
| > | 157855 157856 157857 157858 157859 157860 157861 157862 157863 157864 157865 157866 157867 157868 157869 |
/* Fall through */
if( pMWin->pPartition ){
addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
sqlite3VdbeJumpHere(v, addrGosubFlush);
}
s.regRowid = 0;
addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
VdbeCoverage(v);
if( pMWin->eEnd==TK_PRECEDING ){
int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
|
| ︙ | ︙ | |||
157342 157343 157344 157345 157346 157347 157348 | #define TK_TRUTH 174 #define TK_REGISTER 175 #define TK_VECTOR 176 #define TK_SELECT_COLUMN 177 #define TK_IF_NULL_ROW 178 #define TK_ASTERISK 179 #define TK_SPAN 180 | > | | | 158329 158330 158331 158332 158333 158334 158335 158336 158337 158338 158339 158340 158341 158342 158343 158344 158345 | #define TK_TRUTH 174 #define TK_REGISTER 175 #define TK_VECTOR 176 #define TK_SELECT_COLUMN 177 #define TK_IF_NULL_ROW 178 #define TK_ASTERISK 179 #define TK_SPAN 180 #define TK_ERROR 181 #define TK_SPACE 182 #define TK_ILLEGAL 183 #endif /**************** End token definitions ***************************************/ /* The next sections is a series of control #defines. ** various aspects of the generated parser. ** YYCODETYPE is the data type used to store the integer codes ** that represent terminal and non-terminal symbols. |
| ︙ | ︙ | |||
157403 157404 157405 157406 157407 157408 157409 | ** YY_MAX_REDUCE Maximum value for reduce actions */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int | | | > | | | > > > | | | | | | < | | < < < | | 158391 158392 158393 158394 158395 158396 158397 158398 158399 158400 158401 158402 158403 158404 158405 158406 158407 158408 158409 158410 158411 158412 158413 158414 158415 158416 158417 158418 158419 158420 158421 158422 158423 158424 158425 158426 158427 158428 158429 158430 158431 158432 158433 158434 158435 158436 158437 158438 158439 158440 158441 158442 158443 158444 158445 158446 |
** YY_MAX_REDUCE Maximum value for reduce actions
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
#define YYNOCODE 317
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 101
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
Window* yy49;
ExprList* yy70;
Select* yy81;
With* yy103;
struct FrameBound yy117;
struct {int value; int mask;} yy139;
SrcList* yy153;
TriggerStep* yy157;
Upsert* yy190;
struct TrigEvent yy262;
Cte* yy329;
int yy376;
Expr* yy404;
IdList* yy436;
const char* yy504;
u8 yy552;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define sqlite3ParserARG_SDECL
#define sqlite3ParserARG_PDECL
#define sqlite3ParserARG_PARAM
#define sqlite3ParserARG_FETCH
#define sqlite3ParserARG_STORE
#define sqlite3ParserCTX_SDECL Parse *pParse;
#define sqlite3ParserCTX_PDECL ,Parse *pParse
#define sqlite3ParserCTX_PARAM ,pParse
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
#define YYNSTATE 570
#define YYNRULE 398
#define YYNRULE_WITH_ACTION 337
#define YYNTOKEN 184
#define YY_MAX_SHIFT 569
#define YY_MIN_SHIFTREDUCE 825
#define YY_MAX_SHIFTREDUCE 1222
#define YY_ERROR_ACTION 1223
#define YY_ACCEPT_ACTION 1224
#define YY_NO_ACTION 1225
#define YY_MIN_REDUCE 1226
|
| ︙ | ︙ | |||
157519 157520 157521 157522 157523 157524 157525 | ** 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 **********************************************/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 158507 158508 158509 158510 158511 158512 158513 158514 158515 158516 158517 158518 158519 158520 158521 158522 158523 158524 158525 158526 158527 158528 158529 158530 158531 158532 158533 158534 158535 158536 158537 158538 158539 158540 158541 158542 158543 158544 158545 158546 158547 158548 158549 158550 158551 158552 158553 158554 158555 158556 158557 158558 158559 158560 158561 158562 158563 158564 158565 158566 158567 158568 158569 158570 158571 158572 158573 158574 158575 158576 158577 158578 158579 158580 158581 158582 158583 158584 158585 158586 158587 158588 158589 158590 158591 158592 158593 158594 158595 158596 158597 158598 158599 158600 158601 158602 158603 158604 158605 158606 158607 158608 158609 158610 158611 158612 158613 158614 158615 158616 158617 158618 158619 158620 158621 158622 158623 158624 158625 158626 158627 158628 158629 158630 158631 158632 158633 158634 158635 158636 158637 158638 158639 158640 158641 158642 158643 158644 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 158689 158690 158691 158692 158693 158694 158695 158696 158697 158698 158699 158700 158701 158702 158703 158704 158705 158706 158707 158708 158709 158710 158711 158712 158713 158714 158715 158716 158717 158718 158719 158720 158721 158722 158723 158724 158725 158726 158727 158728 158729 158730 158731 158732 158733 158734 158735 158736 158737 158738 158739 158740 158741 158742 158743 158744 158745 158746 158747 158748 158749 158750 158751 158752 158753 158754 158755 158756 158757 158758 158759 158760 158761 158762 158763 158764 158765 158766 158767 158768 158769 158770 158771 158772 158773 158774 158775 158776 158777 158778 158779 158780 158781 158782 158783 158784 158785 158786 158787 158788 158789 158790 158791 158792 158793 158794 158795 158796 158797 158798 158799 158800 158801 158802 158803 158804 158805 158806 158807 158808 158809 158810 158811 158812 158813 158814 158815 158816 158817 158818 158819 158820 158821 158822 158823 158824 158825 158826 158827 158828 158829 158830 158831 158832 158833 158834 158835 158836 158837 158838 158839 158840 158841 158842 158843 158844 158845 158846 158847 158848 158849 158850 158851 158852 158853 158854 158855 158856 158857 158858 158859 158860 158861 158862 158863 158864 158865 158866 158867 158868 158869 158870 158871 158872 158873 158874 158875 158876 158877 158878 158879 158880 158881 158882 158883 158884 158885 158886 158887 158888 158889 158890 158891 158892 158893 158894 158895 158896 158897 158898 158899 158900 158901 158902 158903 158904 158905 158906 158907 158908 158909 158910 158911 158912 158913 158914 158915 158916 158917 158918 158919 158920 158921 158922 158923 158924 158925 158926 158927 158928 158929 158930 158931 158932 158933 158934 158935 158936 158937 158938 158939 158940 158941 158942 158943 158944 158945 158946 158947 158948 158949 158950 158951 158952 158953 158954 158955 158956 158957 158958 158959 158960 158961 158962 158963 158964 158965 158966 158967 158968 158969 158970 158971 158972 158973 158974 158975 158976 158977 158978 158979 158980 158981 158982 158983 158984 158985 158986 158987 158988 158989 158990 158991 158992 158993 158994 158995 158996 158997 158998 158999 159000 159001 159002 159003 159004 159005 159006 159007 159008 159009 159010 159011 159012 159013 159014 159015 159016 159017 159018 159019 159020 159021 159022 159023 159024 159025 159026 159027 159028 159029 159030 159031 159032 159033 159034 159035 159036 159037 159038 159039 159040 159041 159042 159043 159044 159045 159046 159047 159048 159049 159050 159051 159052 159053 159054 159055 159056 |
** 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 (2023)
static const YYACTIONTYPE yy_action[] = {
/* 0 */ 563, 1295, 563, 1274, 168, 1257, 115, 112, 218, 373,
/* 10 */ 563, 1295, 374, 563, 488, 563, 115, 112, 218, 406,
/* 20 */ 1300, 1300, 41, 41, 41, 41, 514, 1504, 520, 1298,
/* 30 */ 1298, 959, 41, 41, 1260, 71, 71, 51, 51, 960,
/* 40 */ 557, 557, 557, 122, 123, 113, 1200, 1200, 1035, 1038,
/* 50 */ 1028, 1028, 120, 120, 121, 121, 121, 121, 414, 406,
/* 60 */ 273, 273, 273, 273, 115, 112, 218, 115, 112, 218,
/* 70 */ 197, 268, 545, 560, 515, 560, 211, 563, 385, 248,
/* 80 */ 215, 521, 399, 122, 123, 113, 1200, 1200, 1035, 1038,
/* 90 */ 1028, 1028, 120, 120, 121, 121, 121, 121, 540, 13,
/* 100 */ 13, 1259, 119, 119, 119, 119, 118, 118, 117, 117,
/* 110 */ 117, 116, 441, 1176, 419, 197, 446, 320, 512, 1539,
/* 120 */ 1545, 372, 1547, 6, 371, 1176, 1148, 394, 1148, 406,
/* 130 */ 1545, 534, 115, 112, 218, 1415, 99, 30, 121, 121,
/* 140 */ 121, 121, 119, 119, 119, 119, 118, 118, 117, 117,
/* 150 */ 117, 116, 441, 122, 123, 113, 1200, 1200, 1035, 1038,
/* 160 */ 1028, 1028, 120, 120, 121, 121, 121, 121, 31, 1176,
/* 170 */ 1177, 1178, 241, 357, 1558, 501, 498, 497, 317, 124,
/* 180 */ 319, 1176, 1177, 1178, 1176, 496, 119, 119, 119, 119,
/* 190 */ 118, 118, 117, 117, 117, 116, 441, 139, 96, 406,
/* 200 */ 121, 121, 121, 121, 114, 117, 117, 117, 116, 441,
/* 210 */ 541, 1532, 119, 119, 119, 119, 118, 118, 117, 117,
/* 220 */ 117, 116, 441, 122, 123, 113, 1200, 1200, 1035, 1038,
/* 230 */ 1028, 1028, 120, 120, 121, 121, 121, 121, 406, 441,
/* 240 */ 1176, 1177, 1178, 81, 439, 439, 439, 80, 119, 119,
/* 250 */ 119, 119, 118, 118, 117, 117, 117, 116, 441, 488,
/* 260 */ 1176, 318, 122, 123, 113, 1200, 1200, 1035, 1038, 1028,
/* 270 */ 1028, 120, 120, 121, 121, 121, 121, 493, 1025, 1025,
/* 280 */ 1036, 1039, 119, 119, 119, 119, 118, 118, 117, 117,
/* 290 */ 117, 116, 441, 1584, 995, 1224, 1, 1, 569, 2,
/* 300 */ 1228, 1267, 137, 1503, 245, 305, 473, 140, 406, 860,
/* 310 */ 561, 1176, 914, 914, 1308, 359, 1176, 1177, 1178, 462,
/* 320 */ 330, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 330 */ 116, 441, 122, 123, 113, 1200, 1200, 1035, 1038, 1028,
/* 340 */ 1028, 120, 120, 121, 121, 121, 121, 328, 273, 273,
/* 350 */ 1015, 83, 1029, 425, 1564, 569, 2, 1228, 304, 554,
/* 360 */ 925, 560, 305, 944, 140, 860, 1006, 1176, 1177, 1178,
/* 370 */ 1005, 1308, 411, 213, 511, 229, 119, 119, 119, 119,
/* 380 */ 118, 118, 117, 117, 117, 116, 441, 519, 347, 116,
/* 390 */ 441, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 400 */ 116, 441, 1005, 1005, 1007, 273, 273, 445, 563, 16,
/* 410 */ 16, 1590, 563, 1540, 563, 406, 1176, 6, 560, 344,
/* 420 */ 182, 118, 118, 117, 117, 117, 116, 441, 416, 142,
/* 430 */ 71, 71, 229, 563, 71, 71, 55, 55, 203, 122,
/* 440 */ 123, 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120,
/* 450 */ 121, 121, 121, 121, 217, 13, 13, 1176, 406, 568,
/* 460 */ 1400, 1228, 502, 137, 445, 168, 305, 545, 140, 1180,
/* 470 */ 424, 545, 1176, 1177, 1178, 1308, 544, 438, 437, 944,
/* 480 */ 513, 452, 122, 123, 113, 1200, 1200, 1035, 1038, 1028,
/* 490 */ 1028, 120, 120, 121, 121, 121, 121, 315, 119, 119,
/* 500 */ 119, 119, 118, 118, 117, 117, 117, 116, 441, 273,
/* 510 */ 273, 1143, 416, 1176, 1177, 1178, 543, 563, 1143, 304,
/* 520 */ 554, 1561, 560, 1207, 1143, 1207, 1180, 1143, 406, 530,
/* 530 */ 421, 1143, 864, 183, 1143, 143, 229, 562, 32, 71,
/* 540 */ 71, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 550 */ 116, 441, 122, 123, 113, 1200, 1200, 1035, 1038, 1028,
/* 560 */ 1028, 120, 120, 121, 121, 121, 121, 406, 445, 241,
/* 570 */ 1176, 857, 501, 498, 497, 1176, 526, 189, 245, 538,
/* 580 */ 1539, 282, 496, 370, 6, 563, 529, 477, 5, 279,
/* 590 */ 1015, 122, 123, 113, 1200, 1200, 1035, 1038, 1028, 1028,
/* 600 */ 120, 120, 121, 121, 121, 121, 1006, 13, 13, 1414,
/* 610 */ 1005, 119, 119, 119, 119, 118, 118, 117, 117, 117,
/* 620 */ 116, 441, 426, 273, 273, 1176, 1176, 1177, 1178, 1619,
/* 630 */ 392, 1176, 1177, 1178, 1176, 342, 560, 406, 525, 361,
/* 640 */ 430, 1161, 1005, 1005, 1007, 348, 411, 357, 1558, 488,
/* 650 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 660 */ 441, 122, 123, 113, 1200, 1200, 1035, 1038, 1028, 1028,
/* 670 */ 120, 120, 121, 121, 121, 121, 406, 830, 831, 832,
/* 680 */ 1016, 1176, 1177, 1178, 396, 285, 148, 1312, 304, 554,
/* 690 */ 1176, 1177, 1178, 1467, 216, 3, 337, 137, 340, 560,
/* 700 */ 122, 123, 113, 1200, 1200, 1035, 1038, 1028, 1028, 120,
/* 710 */ 120, 121, 121, 121, 121, 563, 504, 946, 273, 273,
/* 720 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 730 */ 441, 560, 1176, 427, 563, 451, 98, 13, 13, 259,
/* 740 */ 276, 356, 507, 351, 506, 246, 406, 361, 469, 1530,
/* 750 */ 1000, 347, 293, 304, 554, 1589, 71, 71, 889, 119,
/* 760 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 441,
/* 770 */ 122, 123, 113, 1200, 1200, 1035, 1038, 1028, 1028, 120,
/* 780 */ 120, 121, 121, 121, 121, 406, 1143, 1078, 1176, 1177,
/* 790 */ 1178, 416, 1080, 300, 150, 995, 1080, 361, 361, 1143,
/* 800 */ 361, 378, 1143, 477, 563, 244, 243, 242, 1278, 122,
/* 810 */ 123, 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120,
/* 820 */ 121, 121, 121, 121, 563, 880, 13, 13, 483, 119,
/* 830 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 441,
/* 840 */ 1176, 191, 540, 563, 147, 149, 13, 13, 328, 457,
/* 850 */ 316, 1083, 1083, 485, 1537, 406, 505, 1530, 6, 1514,
/* 860 */ 284, 192, 1277, 145, 881, 71, 71, 488, 119, 119,
/* 870 */ 119, 119, 118, 118, 117, 117, 117, 116, 441, 122,
/* 880 */ 123, 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120,
/* 890 */ 121, 121, 121, 121, 563, 471, 1176, 1177, 1178, 406,
/* 900 */ 852, 327, 301, 462, 330, 1516, 270, 1530, 1530, 944,
/* 910 */ 1531, 1307, 313, 9, 842, 251, 71, 71, 477, 428,
/* 920 */ 146, 488, 38, 945, 101, 113, 1200, 1200, 1035, 1038,
/* 930 */ 1028, 1028, 120, 120, 121, 121, 121, 121, 119, 119,
/* 940 */ 119, 119, 118, 118, 117, 117, 117, 116, 441, 563,
/* 950 */ 1197, 1099, 563, 436, 563, 1533, 563, 852, 1122, 1617,
/* 960 */ 454, 290, 1617, 546, 251, 1303, 1100, 267, 267, 281,
/* 970 */ 404, 70, 70, 460, 71, 71, 71, 71, 13, 13,
/* 980 */ 560, 1101, 119, 119, 119, 119, 118, 118, 117, 117,
/* 990 */ 117, 116, 441, 542, 104, 273, 273, 273, 273, 1197,
/* 1000 */ 217, 1468, 900, 471, 450, 563, 1473, 1197, 560, 447,
/* 1010 */ 560, 545, 901, 440, 406, 1058, 292, 274, 274, 198,
/* 1020 */ 547, 450, 449, 1473, 1475, 944, 455, 56, 56, 410,
/* 1030 */ 560, 1122, 1618, 379, 406, 1618, 404, 1120, 122, 123,
/* 1040 */ 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120, 121,
/* 1050 */ 121, 121, 121, 1460, 406, 12, 1197, 1512, 122, 123,
/* 1060 */ 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120, 121,
/* 1070 */ 121, 121, 121, 308, 471, 126, 359, 286, 122, 111,
/* 1080 */ 113, 1200, 1200, 1035, 1038, 1028, 1028, 120, 120, 121,
/* 1090 */ 121, 121, 121, 309, 450, 471, 1473, 119, 119, 119,
/* 1100 */ 119, 118, 118, 117, 117, 117, 116, 441, 1176, 563,
/* 1110 */ 1120, 482, 563, 312, 433, 479, 197, 119, 119, 119,
/* 1120 */ 119, 118, 118, 117, 117, 117, 116, 441, 405, 12,
/* 1130 */ 536, 15, 15, 478, 43, 43, 509, 119, 119, 119,
/* 1140 */ 119, 118, 118, 117, 117, 117, 116, 441, 289, 535,
/* 1150 */ 294, 563, 294, 391, 1220, 438, 437, 406, 1154, 403,
/* 1160 */ 402, 1400, 920, 1204, 1176, 1177, 1178, 919, 1206, 291,
/* 1170 */ 1306, 1249, 412, 57, 57, 488, 1205, 563, 556, 412,
/* 1180 */ 1176, 1344, 123, 113, 1200, 1200, 1035, 1038, 1028, 1028,
/* 1190 */ 120, 120, 121, 121, 121, 121, 1400, 1143, 563, 44,
/* 1200 */ 44, 1207, 194, 1207, 273, 273, 1400, 461, 537, 1154,
/* 1210 */ 1143, 108, 555, 1143, 4, 391, 1121, 560, 1538, 335,
/* 1220 */ 58, 58, 6, 1246, 1099, 380, 1400, 376, 558, 1536,
/* 1230 */ 563, 422, 1221, 6, 304, 554, 1176, 1177, 1178, 1100,
/* 1240 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116,
/* 1250 */ 441, 442, 59, 59, 1101, 516, 1535, 273, 273, 563,
/* 1260 */ 6, 563, 110, 552, 563, 528, 423, 413, 169, 548,
/* 1270 */ 560, 108, 555, 137, 4, 551, 484, 272, 215, 222,
/* 1280 */ 211, 60, 60, 61, 61, 98, 62, 62, 558, 273,
/* 1290 */ 273, 563, 1015, 467, 1221, 563, 434, 563, 106, 106,
/* 1300 */ 8, 920, 560, 273, 273, 107, 919, 442, 565, 564,
/* 1310 */ 563, 442, 1005, 45, 45, 464, 560, 46, 46, 47,
/* 1320 */ 47, 84, 202, 552, 1215, 404, 468, 563, 205, 304,
/* 1330 */ 554, 563, 49, 49, 563, 522, 404, 532, 563, 867,
/* 1340 */ 563, 105, 531, 103, 1005, 1005, 1007, 1008, 27, 50,
/* 1350 */ 50, 563, 1015, 63, 63, 475, 64, 64, 106, 106,
/* 1360 */ 65, 65, 14, 14, 17, 107, 563, 442, 565, 564,
/* 1370 */ 563, 303, 1005, 66, 66, 563, 226, 563, 959, 563,
/* 1380 */ 543, 404, 1196, 1343, 871, 278, 960, 456, 128, 128,
/* 1390 */ 563, 1065, 67, 67, 563, 206, 867, 52, 52, 68,
/* 1400 */ 68, 69, 69, 417, 1005, 1005, 1007, 1008, 27, 1563,
/* 1410 */ 1165, 444, 53, 53, 277, 1519, 156, 156, 307, 389,
/* 1420 */ 389, 388, 262, 386, 1165, 444, 839, 321, 277, 108,
/* 1430 */ 555, 523, 4, 389, 389, 388, 262, 386, 563, 223,
/* 1440 */ 839, 311, 326, 1492, 1117, 98, 558, 393, 1065, 310,
/* 1450 */ 563, 476, 563, 223, 563, 311, 879, 878, 1009, 277,
/* 1460 */ 157, 157, 463, 310, 389, 389, 388, 262, 386, 442,
/* 1470 */ 518, 839, 76, 76, 54, 54, 72, 72, 355, 225,
/* 1480 */ 563, 552, 275, 563, 223, 325, 311, 161, 354, 465,
/* 1490 */ 135, 563, 228, 225, 310, 532, 563, 206, 886, 887,
/* 1500 */ 533, 161, 129, 129, 135, 73, 73, 224, 962, 963,
/* 1510 */ 1015, 563, 287, 130, 130, 1009, 106, 106, 131, 131,
/* 1520 */ 563, 224, 563, 107, 225, 442, 565, 564, 997, 1276,
/* 1530 */ 1005, 250, 161, 127, 127, 135, 108, 555, 1077, 4,
/* 1540 */ 1077, 407, 155, 155, 154, 154, 304, 554, 1126, 563,
/* 1550 */ 1331, 563, 224, 558, 470, 407, 563, 250, 563, 1491,
/* 1560 */ 304, 554, 1005, 1005, 1007, 1008, 27, 563, 480, 332,
/* 1570 */ 448, 136, 136, 134, 134, 1340, 442, 336, 132, 132,
/* 1580 */ 133, 133, 563, 1076, 448, 1076, 407, 563, 552, 75,
/* 1590 */ 75, 304, 554, 339, 341, 343, 108, 555, 563, 4,
/* 1600 */ 1577, 299, 532, 563, 77, 77, 1291, 531, 472, 74,
/* 1610 */ 74, 250, 1275, 558, 350, 448, 331, 1015, 360, 98,
/* 1620 */ 42, 42, 1352, 106, 106, 48, 48, 1399, 494, 1327,
/* 1630 */ 107, 247, 442, 565, 564, 345, 442, 1005, 98, 1061,
/* 1640 */ 953, 917, 247, 250, 110, 1552, 550, 850, 552, 918,
/* 1650 */ 144, 1338, 110, 549, 1405, 1256, 1248, 1237, 1236, 1238,
/* 1660 */ 1571, 1324, 208, 390, 489, 265, 363, 200, 365, 1005,
/* 1670 */ 1005, 1007, 1008, 27, 11, 280, 221, 1015, 323, 474,
/* 1680 */ 1274, 367, 212, 106, 106, 924, 1386, 324, 288, 1381,
/* 1690 */ 107, 453, 442, 565, 564, 283, 329, 1005, 1391, 499,
/* 1700 */ 353, 1374, 1464, 108, 555, 1463, 4, 1574, 1390, 397,
/* 1710 */ 1215, 171, 254, 369, 383, 207, 195, 196, 1511, 553,
/* 1720 */ 558, 1509, 415, 1212, 100, 555, 83, 4, 204, 1005,
/* 1730 */ 1005, 1007, 1008, 27, 180, 166, 173, 219, 79, 82,
/* 1740 */ 458, 558, 175, 442, 35, 1387, 176, 459, 177, 178,
/* 1750 */ 492, 231, 96, 1469, 395, 552, 1393, 1392, 36, 466,
/* 1760 */ 1395, 184, 398, 481, 442, 1458, 235, 89, 1480, 487,
/* 1770 */ 266, 334, 237, 188, 490, 400, 552, 338, 238, 508,
/* 1780 */ 1239, 239, 1294, 1293, 1015, 1292, 1285, 429, 91, 871,
/* 1790 */ 106, 106, 1588, 213, 401, 1587, 431, 107, 1264, 442,
/* 1800 */ 565, 564, 1263, 352, 1005, 1015, 1262, 1586, 1557, 517,
/* 1810 */ 432, 106, 106, 1284, 297, 298, 358, 524, 107, 1335,
/* 1820 */ 442, 565, 564, 95, 1336, 1005, 252, 253, 435, 125,
/* 1830 */ 543, 1543, 10, 1444, 377, 1542, 1005, 1005, 1007, 1008,
/* 1840 */ 27, 97, 527, 375, 362, 102, 260, 364, 381, 1317,
/* 1850 */ 382, 1334, 366, 1245, 1333, 1316, 368, 1005, 1005, 1007,
/* 1860 */ 1008, 27, 1359, 1358, 34, 199, 1171, 566, 261, 263,
/* 1870 */ 264, 567, 1234, 158, 1229, 141, 295, 159, 1496, 302,
/* 1880 */ 1497, 1495, 1494, 160, 826, 209, 443, 201, 306, 210,
/* 1890 */ 78, 220, 1075, 138, 1073, 314, 162, 172, 1196, 227,
/* 1900 */ 174, 903, 322, 230, 1089, 179, 163, 164, 418, 408,
/* 1910 */ 409, 170, 181, 85, 86, 420, 87, 165, 1092, 88,
/* 1920 */ 233, 232, 1088, 151, 18, 234, 1081, 250, 333, 1209,
/* 1930 */ 185, 486, 236, 186, 37, 841, 491, 354, 240, 346,
/* 1940 */ 495, 187, 90, 869, 19, 20, 500, 503, 349, 92,
/* 1950 */ 167, 152, 296, 882, 93, 510, 94, 1159, 153, 1041,
/* 1960 */ 1128, 39, 214, 269, 1127, 271, 249, 952, 190, 947,
/* 1970 */ 110, 1149, 21, 7, 1153, 22, 1145, 23, 1147, 24,
/* 1980 */ 1133, 25, 1152, 33, 539, 193, 26, 1056, 98, 1042,
/* 1990 */ 1040, 1044, 1098, 1045, 1097, 256, 255, 28, 40, 257,
/* 2000 */ 1010, 851, 109, 29, 913, 559, 384, 387, 258, 1167,
/* 2010 */ 1166, 1225, 1225, 1225, 1579, 1225, 1225, 1225, 1225, 1225,
/* 2020 */ 1225, 1225, 1578,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 192, 221, 192, 223, 192, 214, 272, 273, 274, 217,
/* 10 */ 192, 231, 217, 192, 192, 192, 272, 273, 274, 19,
/* 20 */ 233, 234, 214, 215, 214, 215, 203, 293, 203, 233,
/* 30 */ 234, 31, 214, 215, 214, 214, 215, 214, 215, 39,
/* 40 */ 208, 209, 210, 43, 44, 45, 46, 47, 48, 49,
/* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 236, 19,
/* 60 */ 237, 238, 237, 238, 272, 273, 274, 272, 273, 274,
/* 70 */ 192, 211, 251, 250, 251, 250, 26, 192, 200, 254,
/* 80 */ 255, 260, 204, 43, 44, 45, 46, 47, 48, 49,
/* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 192, 214,
/* 100 */ 215, 214, 102, 103, 104, 105, 106, 107, 108, 109,
/* 110 */ 110, 111, 112, 59, 229, 192, 294, 16, 306, 307,
/* 120 */ 312, 313, 312, 311, 314, 59, 86, 204, 88, 19,
/* 130 */ 312, 313, 272, 273, 274, 271, 26, 22, 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, 53, 115,
/* 170 */ 116, 117, 118, 309, 310, 121, 122, 123, 77, 69,
/* 180 */ 79, 115, 116, 117, 59, 131, 102, 103, 104, 105,
/* 190 */ 106, 107, 108, 109, 110, 111, 112, 72, 148, 19,
/* 200 */ 54, 55, 56, 57, 58, 108, 109, 110, 111, 112,
/* 210 */ 304, 305, 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, 112,
/* 240 */ 115, 116, 117, 24, 208, 209, 210, 67, 102, 103,
/* 250 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 192,
/* 260 */ 59, 160, 43, 44, 45, 46, 47, 48, 49, 50,
/* 270 */ 51, 52, 53, 54, 55, 56, 57, 19, 46, 47,
/* 280 */ 48, 49, 102, 103, 104, 105, 106, 107, 108, 109,
/* 290 */ 110, 111, 112, 213, 73, 184, 185, 186, 187, 188,
/* 300 */ 189, 221, 81, 236, 46, 194, 192, 196, 19, 59,
/* 310 */ 133, 59, 135, 136, 203, 192, 115, 116, 117, 127,
/* 320 */ 128, 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, 126, 237, 238,
/* 350 */ 100, 150, 120, 230, 186, 187, 188, 189, 137, 138,
/* 360 */ 108, 250, 194, 26, 196, 115, 116, 115, 116, 117,
/* 370 */ 120, 203, 114, 164, 165, 264, 102, 103, 104, 105,
/* 380 */ 106, 107, 108, 109, 110, 111, 112, 192, 130, 111,
/* 390 */ 112, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 400 */ 111, 112, 152, 153, 154, 237, 238, 296, 192, 214,
/* 410 */ 215, 228, 192, 307, 192, 19, 59, 311, 250, 23,
/* 420 */ 22, 106, 107, 108, 109, 110, 111, 112, 192, 72,
/* 430 */ 214, 215, 264, 192, 214, 215, 214, 215, 149, 43,
/* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 450 */ 54, 55, 56, 57, 117, 214, 215, 59, 19, 187,
/* 460 */ 192, 189, 23, 81, 296, 192, 194, 251, 196, 59,
/* 470 */ 229, 251, 115, 116, 117, 203, 260, 106, 107, 142,
/* 480 */ 260, 267, 43, 44, 45, 46, 47, 48, 49, 50,
/* 490 */ 51, 52, 53, 54, 55, 56, 57, 261, 102, 103,
/* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 237,
/* 510 */ 238, 76, 192, 115, 116, 117, 144, 192, 76, 137,
/* 520 */ 138, 192, 250, 152, 89, 154, 116, 92, 19, 87,
/* 530 */ 262, 89, 23, 22, 92, 163, 264, 192, 22, 214,
/* 540 */ 215, 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, 296, 118,
/* 570 */ 59, 23, 121, 122, 123, 59, 251, 26, 46, 306,
/* 580 */ 307, 261, 131, 192, 311, 192, 144, 192, 22, 203,
/* 590 */ 100, 43, 44, 45, 46, 47, 48, 49, 50, 51,
/* 600 */ 52, 53, 54, 55, 56, 57, 116, 214, 215, 271,
/* 610 */ 120, 102, 103, 104, 105, 106, 107, 108, 109, 110,
/* 620 */ 111, 112, 229, 237, 238, 59, 115, 116, 117, 299,
/* 630 */ 300, 115, 116, 117, 59, 16, 250, 19, 192, 192,
/* 640 */ 19, 23, 152, 153, 154, 24, 114, 309, 310, 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, 7, 8, 9,
/* 680 */ 23, 115, 116, 117, 203, 290, 239, 238, 137, 138,
/* 690 */ 115, 116, 117, 236, 192, 22, 77, 81, 79, 250,
/* 700 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
/* 710 */ 53, 54, 55, 56, 57, 192, 95, 142, 237, 238,
/* 720 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 730 */ 112, 250, 59, 112, 192, 119, 26, 214, 215, 118,
/* 740 */ 119, 120, 121, 122, 123, 124, 19, 192, 267, 302,
/* 750 */ 23, 130, 229, 137, 138, 23, 214, 215, 26, 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, 76, 11, 115, 116,
/* 790 */ 117, 192, 29, 251, 239, 73, 33, 192, 192, 89,
/* 800 */ 192, 192, 92, 192, 192, 126, 127, 128, 224, 43,
/* 810 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
/* 820 */ 54, 55, 56, 57, 192, 35, 214, 215, 65, 102,
/* 830 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
/* 840 */ 59, 229, 192, 192, 239, 239, 214, 215, 126, 127,
/* 850 */ 128, 126, 127, 128, 307, 19, 66, 302, 311, 192,
/* 860 */ 261, 229, 224, 22, 74, 214, 215, 192, 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, 192, 115, 116, 117, 19,
/* 900 */ 59, 290, 251, 127, 128, 192, 23, 302, 302, 26,
/* 910 */ 302, 236, 192, 22, 21, 24, 214, 215, 192, 129,
/* 920 */ 22, 192, 24, 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, 192,
/* 950 */ 59, 12, 192, 251, 192, 305, 192, 116, 22, 23,
/* 960 */ 242, 203, 26, 203, 24, 236, 27, 237, 238, 266,
/* 970 */ 252, 214, 215, 80, 214, 215, 214, 215, 214, 215,
/* 980 */ 250, 42, 102, 103, 104, 105, 106, 107, 108, 109,
/* 990 */ 110, 111, 112, 229, 158, 237, 238, 237, 238, 59,
/* 1000 */ 117, 281, 63, 192, 192, 192, 192, 116, 250, 192,
/* 1010 */ 250, 251, 73, 251, 19, 122, 290, 237, 238, 24,
/* 1020 */ 260, 209, 210, 209, 210, 142, 242, 214, 215, 197,
/* 1030 */ 250, 22, 23, 276, 19, 26, 252, 101, 43, 44,
/* 1040 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1050 */ 55, 56, 57, 160, 19, 211, 116, 192, 43, 44,
/* 1060 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1070 */ 55, 56, 57, 192, 192, 22, 192, 266, 43, 44,
/* 1080 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
/* 1090 */ 55, 56, 57, 192, 282, 192, 282, 102, 103, 104,
/* 1100 */ 105, 106, 107, 108, 109, 110, 111, 112, 59, 192,
/* 1110 */ 101, 279, 192, 192, 230, 283, 192, 102, 103, 104,
/* 1120 */ 105, 106, 107, 108, 109, 110, 111, 112, 204, 211,
/* 1130 */ 66, 214, 215, 289, 214, 215, 108, 102, 103, 104,
/* 1140 */ 105, 106, 107, 108, 109, 110, 111, 112, 266, 85,
/* 1150 */ 226, 192, 228, 22, 23, 106, 107, 19, 94, 106,
/* 1160 */ 107, 192, 134, 114, 115, 116, 117, 139, 119, 266,
/* 1170 */ 203, 206, 207, 214, 215, 192, 127, 192, 206, 207,
/* 1180 */ 59, 192, 44, 45, 46, 47, 48, 49, 50, 51,
/* 1190 */ 52, 53, 54, 55, 56, 57, 192, 76, 192, 214,
/* 1200 */ 215, 152, 284, 154, 237, 238, 192, 289, 87, 145,
/* 1210 */ 89, 19, 20, 92, 22, 22, 23, 250, 307, 236,
/* 1220 */ 214, 215, 311, 203, 12, 247, 192, 249, 36, 307,
/* 1230 */ 192, 262, 101, 311, 137, 138, 115, 116, 117, 27,
/* 1240 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
/* 1250 */ 112, 59, 214, 215, 42, 203, 307, 237, 238, 192,
/* 1260 */ 311, 192, 26, 71, 192, 144, 262, 297, 298, 203,
/* 1270 */ 250, 19, 20, 81, 22, 63, 262, 254, 255, 15,
/* 1280 */ 26, 214, 215, 214, 215, 26, 214, 215, 36, 237,
/* 1290 */ 238, 192, 100, 114, 101, 192, 262, 192, 106, 107,
/* 1300 */ 48, 134, 250, 237, 238, 113, 139, 115, 116, 117,
/* 1310 */ 192, 59, 120, 214, 215, 242, 250, 214, 215, 214,
/* 1320 */ 215, 148, 149, 71, 60, 252, 242, 192, 149, 137,
/* 1330 */ 138, 192, 214, 215, 192, 19, 252, 85, 192, 59,
/* 1340 */ 192, 157, 90, 159, 152, 153, 154, 155, 156, 214,
/* 1350 */ 215, 192, 100, 214, 215, 19, 214, 215, 106, 107,
/* 1360 */ 214, 215, 214, 215, 22, 113, 192, 115, 116, 117,
/* 1370 */ 192, 242, 120, 214, 215, 192, 24, 192, 31, 192,
/* 1380 */ 144, 252, 26, 192, 125, 99, 39, 192, 214, 215,
/* 1390 */ 192, 59, 214, 215, 192, 141, 116, 214, 215, 214,
/* 1400 */ 215, 214, 215, 61, 152, 153, 154, 155, 156, 0,
/* 1410 */ 1, 2, 214, 215, 5, 192, 214, 215, 132, 10,
/* 1420 */ 11, 12, 13, 14, 1, 2, 17, 192, 5, 19,
/* 1430 */ 20, 115, 22, 10, 11, 12, 13, 14, 192, 30,
/* 1440 */ 17, 32, 23, 192, 23, 26, 36, 26, 116, 40,
/* 1450 */ 192, 115, 192, 30, 192, 32, 119, 120, 59, 5,
/* 1460 */ 214, 215, 128, 40, 10, 11, 12, 13, 14, 59,
/* 1470 */ 19, 17, 214, 215, 214, 215, 214, 215, 120, 70,
/* 1480 */ 192, 71, 22, 192, 30, 151, 32, 78, 130, 128,
/* 1490 */ 81, 192, 140, 70, 40, 85, 192, 141, 7, 8,
/* 1500 */ 90, 78, 214, 215, 81, 214, 215, 98, 83, 84,
/* 1510 */ 100, 192, 151, 214, 215, 116, 106, 107, 214, 215,
/* 1520 */ 192, 98, 192, 113, 70, 115, 116, 117, 23, 224,
/* 1530 */ 120, 26, 78, 214, 215, 81, 19, 20, 152, 22,
/* 1540 */ 154, 132, 214, 215, 214, 215, 137, 138, 97, 192,
/* 1550 */ 256, 192, 98, 36, 23, 132, 192, 26, 192, 192,
/* 1560 */ 137, 138, 152, 153, 154, 155, 156, 192, 192, 192,
/* 1570 */ 161, 214, 215, 214, 215, 192, 59, 192, 214, 215,
/* 1580 */ 214, 215, 192, 152, 161, 154, 132, 192, 71, 214,
/* 1590 */ 215, 137, 138, 192, 192, 192, 19, 20, 192, 22,
/* 1600 */ 140, 253, 85, 192, 214, 215, 192, 90, 23, 214,
/* 1610 */ 215, 26, 192, 36, 192, 161, 23, 100, 192, 26,
/* 1620 */ 214, 215, 192, 106, 107, 214, 215, 192, 23, 192,
/* 1630 */ 113, 26, 115, 116, 117, 23, 59, 120, 26, 23,
/* 1640 */ 23, 23, 26, 26, 26, 316, 234, 23, 71, 23,
/* 1650 */ 26, 192, 26, 192, 192, 192, 192, 192, 192, 192,
/* 1660 */ 192, 253, 212, 190, 286, 285, 253, 240, 253, 152,
/* 1670 */ 153, 154, 155, 156, 241, 243, 295, 100, 291, 291,
/* 1680 */ 223, 253, 227, 106, 107, 108, 269, 244, 244, 265,
/* 1690 */ 113, 257, 115, 116, 117, 257, 243, 120, 269, 218,
/* 1700 */ 217, 265, 217, 19, 20, 217, 22, 195, 269, 269,
/* 1710 */ 60, 295, 140, 257, 243, 241, 247, 247, 199, 278,
/* 1720 */ 36, 199, 199, 38, 19, 20, 150, 22, 149, 152,
/* 1730 */ 153, 154, 155, 156, 22, 43, 232, 295, 292, 292,
/* 1740 */ 18, 36, 235, 59, 268, 270, 235, 199, 235, 235,
/* 1750 */ 18, 198, 148, 281, 244, 71, 270, 270, 268, 244,
/* 1760 */ 232, 232, 244, 199, 59, 244, 198, 157, 288, 62,
/* 1770 */ 199, 287, 198, 22, 219, 219, 71, 199, 198, 114,
/* 1780 */ 199, 198, 216, 216, 100, 216, 225, 64, 22, 125,
/* 1790 */ 106, 107, 222, 164, 219, 222, 24, 113, 216, 115,
/* 1800 */ 116, 117, 218, 216, 120, 100, 216, 216, 310, 303,
/* 1810 */ 112, 106, 107, 225, 280, 280, 219, 143, 113, 259,
/* 1820 */ 115, 116, 117, 114, 259, 120, 199, 91, 82, 147,
/* 1830 */ 144, 315, 22, 275, 199, 315, 152, 153, 154, 155,
/* 1840 */ 156, 146, 145, 247, 258, 157, 25, 258, 245, 248,
/* 1850 */ 244, 259, 258, 202, 259, 248, 258, 152, 153, 154,
/* 1860 */ 155, 156, 263, 263, 26, 246, 13, 201, 193, 193,
/* 1870 */ 6, 191, 191, 205, 191, 220, 220, 205, 211, 277,
/* 1880 */ 211, 211, 211, 205, 4, 212, 3, 22, 162, 212,
/* 1890 */ 211, 15, 23, 16, 23, 138, 129, 150, 26, 24,
/* 1900 */ 141, 20, 16, 143, 1, 141, 129, 129, 61, 301,
/* 1910 */ 301, 298, 150, 53, 53, 37, 53, 129, 115, 53,
/* 1920 */ 140, 34, 1, 5, 22, 114, 68, 26, 160, 75,
/* 1930 */ 68, 41, 140, 114, 24, 20, 19, 130, 124, 23,
/* 1940 */ 67, 22, 22, 59, 22, 22, 67, 96, 24, 22,
/* 1950 */ 37, 23, 67, 28, 148, 22, 26, 23, 23, 23,
/* 1960 */ 23, 22, 140, 23, 97, 23, 34, 115, 22, 142,
/* 1970 */ 26, 75, 34, 44, 75, 34, 88, 34, 86, 34,
/* 1980 */ 23, 34, 93, 22, 24, 26, 34, 23, 26, 23,
/* 1990 */ 23, 23, 23, 11, 23, 22, 26, 22, 22, 140,
/* 2000 */ 23, 23, 22, 22, 134, 26, 23, 15, 140, 1,
/* 2010 */ 1, 317, 317, 317, 140, 317, 317, 317, 317, 317,
/* 2020 */ 317, 317, 140, 317, 317, 317, 317, 317, 317, 317,
/* 2030 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2040 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2050 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2060 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2070 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2080 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2090 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2100 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2110 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2120 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2130 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2140 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2150 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2160 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2170 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2180 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2190 */ 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
/* 2200 */ 317, 317, 317, 317, 317, 317, 317,
};
#define YY_SHIFT_COUNT (569)
#define YY_SHIFT_MIN (0)
#define YY_SHIFT_MAX (2009)
static const unsigned short int yy_shift_ofst[] = {
/* 0 */ 1423, 1409, 1454, 1192, 1192, 382, 1252, 1410, 1517, 1684,
/* 10 */ 1684, 1684, 221, 0, 0, 180, 1015, 1684, 1684, 1684,
/* 20 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
/* 30 */ 1049, 1049, 1121, 1121, 54, 616, 382, 382, 382, 382,
/* 40 */ 382, 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, 1577, 1684,
/* 80 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
/* 90 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
/* 100 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684,
/* 110 */ 1684, 1684, 1684, 1705, 1684, 1684, 1684, 1684, 1684, 1684,
/* 120 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 146, 84, 84,
/* 130 */ 84, 84, 84, 274, 315, 125, 97, 357, 66, 66,
/* 140 */ 893, 258, 66, 66, 371, 371, 66, 551, 551, 551,
/* 150 */ 551, 192, 209, 209, 278, 127, 2023, 2023, 621, 621,
/* 160 */ 621, 201, 398, 398, 398, 398, 939, 939, 442, 936,
/* 170 */ 1009, 66, 66, 66, 66, 66, 66, 66, 66, 66,
/* 180 */ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
/* 190 */ 66, 710, 710, 66, 776, 435, 435, 410, 410, 372,
/* 200 */ 1097, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 250, 490,
/* 210 */ 490, 511, 451, 516, 252, 566, 575, 781, 673, 66,
/* 220 */ 66, 66, 66, 66, 66, 66, 66, 66, 66, 722,
/* 230 */ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
/* 240 */ 66, 66, 790, 790, 790, 66, 66, 66, 883, 66,
/* 250 */ 66, 66, 891, 1064, 66, 66, 1212, 66, 66, 66,
/* 260 */ 66, 66, 66, 66, 66, 725, 763, 177, 940, 940,
/* 270 */ 940, 940, 337, 177, 177, 1028, 1053, 670, 1264, 1179,
/* 280 */ 1173, 1254, 1316, 1173, 1316, 1336, 50, 1179, 1179, 50,
/* 290 */ 1179, 1254, 1336, 1259, 732, 532, 1347, 1347, 1347, 1316,
/* 300 */ 1236, 1236, 1184, 1356, 1167, 898, 1650, 1650, 1572, 1572,
/* 310 */ 1685, 1685, 1572, 1576, 1579, 1712, 1692, 1722, 1722, 1722,
/* 320 */ 1722, 1572, 1732, 1604, 1579, 1579, 1604, 1712, 1692, 1604,
/* 330 */ 1692, 1604, 1572, 1732, 1610, 1707, 1572, 1732, 1751, 1572,
/* 340 */ 1732, 1572, 1732, 1751, 1665, 1665, 1665, 1723, 1766, 1766,
/* 350 */ 1751, 1665, 1664, 1665, 1723, 1665, 1665, 1629, 1772, 1698,
/* 360 */ 1698, 1751, 1674, 1709, 1674, 1709, 1674, 1709, 1674, 1709,
/* 370 */ 1572, 1736, 1736, 1746, 1746, 1682, 1686, 1810, 1572, 1688,
/* 380 */ 1682, 1695, 1697, 1604, 1821, 1838, 1853, 1853, 1864, 1864,
/* 390 */ 1864, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023,
/* 400 */ 2023, 2023, 2023, 2023, 2023, 2023, 232, 101, 1131, 1193,
/* 410 */ 619, 679, 841, 1421, 1286, 115, 1352, 1334, 1361, 1419,
/* 420 */ 1342, 1505, 1531, 1585, 1593, 1605, 1612, 1280, 1337, 1491,
/* 430 */ 1358, 1451, 1332, 1616, 1617, 1425, 1618, 1386, 1431, 1624,
/* 440 */ 1626, 1399, 1460, 1880, 1883, 1865, 1726, 1876, 1877, 1869,
/* 450 */ 1871, 1757, 1747, 1767, 1872, 1872, 1875, 1759, 1881, 1760,
/* 460 */ 1886, 1903, 1764, 1777, 1872, 1778, 1847, 1878, 1872, 1762,
/* 470 */ 1860, 1861, 1863, 1866, 1788, 1803, 1887, 1780, 1921, 1918,
/* 480 */ 1902, 1811, 1768, 1858, 1901, 1862, 1854, 1890, 1792, 1819,
/* 490 */ 1910, 1915, 1917, 1807, 1814, 1919, 1873, 1920, 1922, 1916,
/* 500 */ 1923, 1879, 1884, 1924, 1851, 1925, 1927, 1885, 1913, 1928,
/* 510 */ 1806, 1933, 1934, 1935, 1936, 1930, 1937, 1939, 1867, 1822,
/* 520 */ 1940, 1942, 1852, 1932, 1946, 1827, 1944, 1938, 1941, 1943,
/* 530 */ 1945, 1888, 1896, 1892, 1929, 1899, 1889, 1947, 1957, 1961,
/* 540 */ 1960, 1959, 1962, 1952, 1964, 1944, 1966, 1967, 1968, 1969,
/* 550 */ 1970, 1971, 1973, 1982, 1975, 1976, 1977, 1978, 1980, 1981,
/* 560 */ 1979, 1870, 1859, 1868, 1874, 1882, 1983, 1992, 2008, 2009,
};
#define YY_REDUCE_COUNT (405)
#define YY_REDUCE_MIN (-266)
#define YY_REDUCE_MAX (1683)
static const short yy_reduce_ofst[] = {
/* 0 */ 111, 168, 272, 760, -177, -175, -192, -190, -182, -179,
/* 10 */ 216, 220, 481, -208, -205, -266, -140, -115, 241, 393,
/* 20 */ 523, 325, 612, 632, 542, 651, 764, 757, 702, 762,
/* 30 */ 812, 814, -188, 273, 924, 386, 758, 967, 1020, 1052,
/* 40 */ 1066, -256, -256, -256, -256, -256, -256, -256, -256, -256,
/* 50 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
/* 60 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
/* 70 */ -256, -256, -256, -256, -256, -256, -256, -256, 195, 222,
/* 80 */ 813, 917, 920, 959, 985, 1006, 1038, 1067, 1069, 1072,
/* 90 */ 1099, 1103, 1105, 1118, 1135, 1139, 1142, 1146, 1148, 1159,
/* 100 */ 1174, 1178, 1183, 1185, 1187, 1198, 1202, 1246, 1258, 1260,
/* 110 */ 1262, 1288, 1291, 1299, 1304, 1319, 1328, 1330, 1357, 1359,
/* 120 */ 1364, 1366, 1375, 1390, 1395, 1406, 1411, -256, -256, -256,
/* 130 */ -256, -256, -256, -256, -256, 447, -256, 555, -178, 605,
/* 140 */ 832, -220, 606, -94, -168, 36, -122, 730, 780, 730,
/* 150 */ 780, 918, -136, 338, -256, -256, -256, -256, 80, 80,
/* 160 */ 80, 720, 703, 811, 882, 903, -213, -204, 106, 330,
/* 170 */ 330, -77, 236, 320, 599, 67, 457, 675, 729, 395,
/* 180 */ 268, 611, 969, 1004, 726, 1014, 983, 123, 884, 608,
/* 190 */ 1034, 547, 911, 650, 844, 922, 949, 965, 972, 978,
/* 200 */ 449, 970, 718, 784, 1073, 1084, 1023, 1129, -209, -180,
/* 210 */ -113, 114, 183, 329, 345, 391, 446, 502, 609, 667,
/* 220 */ 713, 817, 865, 881, 901, 921, 989, 1191, 1195, 214,
/* 230 */ 1223, 1235, 1251, 1367, 1376, 1377, 1383, 1385, 1401, 1402,
/* 240 */ 1403, 1414, 584, 638, 1305, 1420, 1422, 1426, 1294, 1430,
/* 250 */ 1435, 1437, 1348, 1329, 1459, 1461, 1412, 1462, 345, 1463,
/* 260 */ 1464, 1465, 1466, 1467, 1468, 1378, 1380, 1427, 1408, 1413,
/* 270 */ 1415, 1428, 1294, 1427, 1427, 1433, 1450, 1473, 1381, 1417,
/* 280 */ 1424, 1432, 1434, 1436, 1438, 1387, 1443, 1429, 1439, 1444,
/* 290 */ 1440, 1453, 1388, 1481, 1455, 1457, 1483, 1485, 1488, 1456,
/* 300 */ 1469, 1470, 1441, 1471, 1474, 1512, 1416, 1442, 1519, 1522,
/* 310 */ 1446, 1447, 1523, 1472, 1475, 1476, 1504, 1507, 1511, 1513,
/* 320 */ 1514, 1548, 1553, 1510, 1486, 1487, 1515, 1490, 1528, 1518,
/* 330 */ 1529, 1521, 1564, 1568, 1480, 1484, 1571, 1574, 1555, 1578,
/* 340 */ 1580, 1581, 1583, 1556, 1566, 1567, 1569, 1561, 1570, 1573,
/* 350 */ 1575, 1582, 1584, 1587, 1588, 1590, 1591, 1498, 1506, 1534,
/* 360 */ 1535, 1597, 1560, 1586, 1565, 1589, 1592, 1594, 1595, 1598,
/* 370 */ 1627, 1516, 1520, 1599, 1600, 1601, 1596, 1558, 1635, 1602,
/* 380 */ 1607, 1619, 1603, 1606, 1651, 1666, 1675, 1676, 1680, 1681,
/* 390 */ 1683, 1608, 1609, 1613, 1668, 1667, 1669, 1670, 1671, 1672,
/* 400 */ 1655, 1656, 1673, 1677, 1679, 1678,
};
static const YYACTIONTYPE yy_default[] = {
/* 0 */ 1623, 1623, 1623, 1453, 1223, 1332, 1223, 1223, 1223, 1453,
/* 10 */ 1453, 1453, 1223, 1362, 1362, 1506, 1254, 1223, 1223, 1223,
/* 20 */ 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1452, 1223, 1223,
/* 30 */ 1223, 1223, 1541, 1541, 1223, 1223, 1223, 1223, 1223, 1223,
/* 40 */ 1223, 1223, 1371, 1223, 1378, 1223, 1223, 1223, 1223, 1223,
|
| ︙ | ︙ | |||
158313 158314 158315 158316 158317 158318 158319 158320 158321 158322 158323 158324 158325 158326 |
0, /* TRUTH => nothing */
0, /* REGISTER => nothing */
0, /* VECTOR => nothing */
0, /* SELECT_COLUMN => nothing */
0, /* IF_NULL_ROW => nothing */
0, /* ASTERISK => nothing */
0, /* SPAN => nothing */
0, /* SPACE => nothing */
0, /* ILLEGAL => nothing */
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
| > | 159302 159303 159304 159305 159306 159307 159308 159309 159310 159311 159312 159313 159314 159315 159316 |
0, /* TRUTH => nothing */
0, /* REGISTER => nothing */
0, /* VECTOR => nothing */
0, /* SELECT_COLUMN => nothing */
0, /* IF_NULL_ROW => nothing */
0, /* ASTERISK => nothing */
0, /* SPAN => nothing */
0, /* ERROR => nothing */
0, /* SPACE => nothing */
0, /* ILLEGAL => nothing */
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
** parser's stack. Information stored includes:
|
| ︙ | ︙ | |||
158584 158585 158586 158587 158588 158589 158590 | /* 174 */ "TRUTH", /* 175 */ "REGISTER", /* 176 */ "VECTOR", /* 177 */ "SELECT_COLUMN", /* 178 */ "IF_NULL_ROW", /* 179 */ "ASTERISK", /* 180 */ "SPAN", | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 159574 159575 159576 159577 159578 159579 159580 159581 159582 159583 159584 159585 159586 159587 159588 159589 159590 159591 159592 159593 159594 159595 159596 159597 159598 159599 159600 159601 159602 159603 159604 159605 159606 159607 159608 159609 159610 159611 159612 159613 159614 159615 159616 159617 159618 159619 159620 159621 159622 159623 159624 159625 159626 159627 159628 159629 159630 159631 159632 159633 159634 159635 159636 159637 159638 159639 159640 159641 159642 159643 159644 159645 159646 159647 159648 159649 159650 159651 159652 159653 159654 159655 159656 159657 159658 159659 159660 159661 159662 159663 159664 159665 159666 159667 159668 159669 159670 159671 159672 159673 159674 159675 159676 159677 159678 159679 159680 159681 159682 159683 159684 159685 159686 159687 159688 159689 159690 159691 159692 159693 159694 159695 159696 159697 159698 159699 159700 159701 159702 159703 159704 159705 159706 159707 159708 159709 159710 159711 159712 159713 159714 159715 159716 159717 159718 159719 159720 159721 159722 159723 |
/* 174 */ "TRUTH",
/* 175 */ "REGISTER",
/* 176 */ "VECTOR",
/* 177 */ "SELECT_COLUMN",
/* 178 */ "IF_NULL_ROW",
/* 179 */ "ASTERISK",
/* 180 */ "SPAN",
/* 181 */ "ERROR",
/* 182 */ "SPACE",
/* 183 */ "ILLEGAL",
/* 184 */ "input",
/* 185 */ "cmdlist",
/* 186 */ "ecmd",
/* 187 */ "cmdx",
/* 188 */ "explain",
/* 189 */ "cmd",
/* 190 */ "transtype",
/* 191 */ "trans_opt",
/* 192 */ "nm",
/* 193 */ "savepoint_opt",
/* 194 */ "create_table",
/* 195 */ "create_table_args",
/* 196 */ "createkw",
/* 197 */ "temp",
/* 198 */ "ifnotexists",
/* 199 */ "dbnm",
/* 200 */ "columnlist",
/* 201 */ "conslist_opt",
/* 202 */ "table_options",
/* 203 */ "select",
/* 204 */ "columnname",
/* 205 */ "carglist",
/* 206 */ "typetoken",
/* 207 */ "typename",
/* 208 */ "signed",
/* 209 */ "plus_num",
/* 210 */ "minus_num",
/* 211 */ "scanpt",
/* 212 */ "scantok",
/* 213 */ "ccons",
/* 214 */ "term",
/* 215 */ "expr",
/* 216 */ "onconf",
/* 217 */ "sortorder",
/* 218 */ "autoinc",
/* 219 */ "eidlist_opt",
/* 220 */ "refargs",
/* 221 */ "defer_subclause",
/* 222 */ "generated",
/* 223 */ "refarg",
/* 224 */ "refact",
/* 225 */ "init_deferred_pred_opt",
/* 226 */ "conslist",
/* 227 */ "tconscomma",
/* 228 */ "tcons",
/* 229 */ "sortlist",
/* 230 */ "eidlist",
/* 231 */ "defer_subclause_opt",
/* 232 */ "orconf",
/* 233 */ "resolvetype",
/* 234 */ "raisetype",
/* 235 */ "ifexists",
/* 236 */ "fullname",
/* 237 */ "selectnowith",
/* 238 */ "oneselect",
/* 239 */ "wqlist",
/* 240 */ "multiselect_op",
/* 241 */ "distinct",
/* 242 */ "selcollist",
/* 243 */ "from",
/* 244 */ "where_opt",
/* 245 */ "groupby_opt",
/* 246 */ "having_opt",
/* 247 */ "orderby_opt",
/* 248 */ "limit_opt",
/* 249 */ "window_clause",
/* 250 */ "values",
/* 251 */ "nexprlist",
/* 252 */ "sclp",
/* 253 */ "as",
/* 254 */ "seltablist",
/* 255 */ "stl_prefix",
/* 256 */ "joinop",
/* 257 */ "indexed_opt",
/* 258 */ "on_opt",
/* 259 */ "using_opt",
/* 260 */ "exprlist",
/* 261 */ "xfullname",
/* 262 */ "idlist",
/* 263 */ "nulls",
/* 264 */ "with",
/* 265 */ "where_opt_ret",
/* 266 */ "setlist",
/* 267 */ "insert_cmd",
/* 268 */ "idlist_opt",
/* 269 */ "upsert",
/* 270 */ "returning",
/* 271 */ "filter_over",
/* 272 */ "likeop",
/* 273 */ "between_op",
/* 274 */ "in_op",
/* 275 */ "paren_exprlist",
/* 276 */ "case_operand",
/* 277 */ "case_exprlist",
/* 278 */ "case_else",
/* 279 */ "uniqueflag",
/* 280 */ "collate",
/* 281 */ "vinto",
/* 282 */ "nmnum",
/* 283 */ "trigger_decl",
/* 284 */ "trigger_cmd_list",
/* 285 */ "trigger_time",
/* 286 */ "trigger_event",
/* 287 */ "foreach_clause",
/* 288 */ "when_clause",
/* 289 */ "trigger_cmd",
/* 290 */ "trnm",
/* 291 */ "tridxby",
/* 292 */ "database_kw_opt",
/* 293 */ "key_opt",
/* 294 */ "add_column_fullname",
/* 295 */ "kwcolumn_opt",
/* 296 */ "create_vtab",
/* 297 */ "vtabarglist",
/* 298 */ "vtabarg",
/* 299 */ "vtabargtoken",
/* 300 */ "lp",
/* 301 */ "anylist",
/* 302 */ "wqitem",
/* 303 */ "wqas",
/* 304 */ "windowdefn_list",
/* 305 */ "windowdefn",
/* 306 */ "window",
/* 307 */ "frame_opt",
/* 308 */ "part_opt",
/* 309 */ "filter_clause",
/* 310 */ "over_clause",
/* 311 */ "range_or_rows",
/* 312 */ "frame_bound",
/* 313 */ "frame_bound_s",
/* 314 */ "frame_bound_e",
/* 315 */ "frame_exclude_opt",
/* 316 */ "frame_exclude",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
|
| ︙ | ︙ | |||
159249 159250 159251 159252 159253 159254 159255 |
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | > | | | | | | | | | | | | 160240 160241 160242 160243 160244 160245 160246 160247 160248 160249 160250 160251 160252 160253 160254 160255 160256 160257 160258 160259 160260 160261 160262 160263 160264 160265 160266 160267 160268 160269 160270 160271 160272 160273 160274 160275 160276 160277 160278 160279 160280 160281 160282 160283 160284 160285 160286 160287 160288 160289 160290 160291 160292 160293 160294 160295 160296 160297 160298 160299 160300 160301 160302 160303 160304 160305 160306 160307 160308 160309 160310 160311 160312 160313 160314 160315 160316 160317 160318 160319 160320 160321 160322 160323 160324 160325 160326 160327 160328 160329 160330 160331 160332 160333 160334 160335 160336 160337 160338 160339 160340 160341 160342 160343 160344 160345 160346 |
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
case 203: /* select */
case 237: /* selectnowith */
case 238: /* oneselect */
case 250: /* values */
{
sqlite3SelectDelete(pParse->db, (yypminor->yy81));
}
break;
case 214: /* term */
case 215: /* expr */
case 244: /* where_opt */
case 246: /* having_opt */
case 258: /* on_opt */
case 265: /* where_opt_ret */
case 276: /* case_operand */
case 278: /* case_else */
case 281: /* vinto */
case 288: /* when_clause */
case 293: /* key_opt */
case 309: /* filter_clause */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy404));
}
break;
case 219: /* eidlist_opt */
case 229: /* sortlist */
case 230: /* eidlist */
case 242: /* selcollist */
case 245: /* groupby_opt */
case 247: /* orderby_opt */
case 251: /* nexprlist */
case 252: /* sclp */
case 260: /* exprlist */
case 266: /* setlist */
case 275: /* paren_exprlist */
case 277: /* case_exprlist */
case 308: /* part_opt */
{
sqlite3ExprListDelete(pParse->db, (yypminor->yy70));
}
break;
case 236: /* fullname */
case 243: /* from */
case 254: /* seltablist */
case 255: /* stl_prefix */
case 261: /* xfullname */
{
sqlite3SrcListDelete(pParse->db, (yypminor->yy153));
}
break;
case 239: /* wqlist */
{
sqlite3WithDelete(pParse->db, (yypminor->yy103));
}
break;
case 249: /* window_clause */
case 304: /* windowdefn_list */
{
sqlite3WindowListDelete(pParse->db, (yypminor->yy49));
}
break;
case 259: /* using_opt */
case 262: /* idlist */
case 268: /* idlist_opt */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy436));
}
break;
case 271: /* filter_over */
case 305: /* windowdefn */
case 306: /* window */
case 307: /* frame_opt */
case 310: /* over_clause */
{
sqlite3WindowDelete(pParse->db, (yypminor->yy49));
}
break;
case 284: /* trigger_cmd_list */
case 289: /* trigger_cmd */
{
sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy157));
}
break;
case 286: /* trigger_event */
{
sqlite3IdListDelete(pParse->db, (yypminor->yy262).b);
}
break;
case 312: /* frame_bound */
case 313: /* frame_bound_s */
case 314: /* frame_bound_e */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy117).pExpr);
}
break;
/********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */
}
}
|
| ︙ | ︙ | |||
159632 159633 159634 159635 159636 159637 159638 |
yytos->minor.yy0 = yyMinor;
yyTraceShift(yypParser, yyNewState, "Shift");
}
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 160623 160624 160625 160626 160627 160628 160629 160630 160631 160632 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 |
yytos->minor.yy0 = yyMinor;
yyTraceShift(yypParser, yyNewState, "Shift");
}
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
188, /* (0) explain ::= EXPLAIN */
188, /* (1) explain ::= EXPLAIN QUERY PLAN */
187, /* (2) cmdx ::= cmd */
189, /* (3) cmd ::= BEGIN transtype trans_opt */
190, /* (4) transtype ::= */
190, /* (5) transtype ::= DEFERRED */
190, /* (6) transtype ::= IMMEDIATE */
190, /* (7) transtype ::= EXCLUSIVE */
189, /* (8) cmd ::= COMMIT|END trans_opt */
189, /* (9) cmd ::= ROLLBACK trans_opt */
189, /* (10) cmd ::= SAVEPOINT nm */
189, /* (11) cmd ::= RELEASE savepoint_opt nm */
189, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
194, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
196, /* (14) createkw ::= CREATE */
198, /* (15) ifnotexists ::= */
198, /* (16) ifnotexists ::= IF NOT EXISTS */
197, /* (17) temp ::= TEMP */
197, /* (18) temp ::= */
195, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
195, /* (20) create_table_args ::= AS select */
202, /* (21) table_options ::= */
202, /* (22) table_options ::= WITHOUT nm */
204, /* (23) columnname ::= nm typetoken */
206, /* (24) typetoken ::= */
206, /* (25) typetoken ::= typename LP signed RP */
206, /* (26) typetoken ::= typename LP signed COMMA signed RP */
207, /* (27) typename ::= typename ID|STRING */
211, /* (28) scanpt ::= */
212, /* (29) scantok ::= */
213, /* (30) ccons ::= CONSTRAINT nm */
213, /* (31) ccons ::= DEFAULT scantok term */
213, /* (32) ccons ::= DEFAULT LP expr RP */
213, /* (33) ccons ::= DEFAULT PLUS scantok term */
213, /* (34) ccons ::= DEFAULT MINUS scantok term */
213, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
213, /* (36) ccons ::= NOT NULL onconf */
213, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
213, /* (38) ccons ::= UNIQUE onconf */
213, /* (39) ccons ::= CHECK LP expr RP */
213, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
213, /* (41) ccons ::= defer_subclause */
213, /* (42) ccons ::= COLLATE ID|STRING */
222, /* (43) generated ::= LP expr RP */
222, /* (44) generated ::= LP expr RP ID */
218, /* (45) autoinc ::= */
218, /* (46) autoinc ::= AUTOINCR */
220, /* (47) refargs ::= */
220, /* (48) refargs ::= refargs refarg */
223, /* (49) refarg ::= MATCH nm */
223, /* (50) refarg ::= ON INSERT refact */
223, /* (51) refarg ::= ON DELETE refact */
223, /* (52) refarg ::= ON UPDATE refact */
224, /* (53) refact ::= SET NULL */
224, /* (54) refact ::= SET DEFAULT */
224, /* (55) refact ::= CASCADE */
224, /* (56) refact ::= RESTRICT */
224, /* (57) refact ::= NO ACTION */
221, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
221, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
225, /* (60) init_deferred_pred_opt ::= */
225, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
225, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
201, /* (63) conslist_opt ::= */
227, /* (64) tconscomma ::= COMMA */
228, /* (65) tcons ::= CONSTRAINT nm */
228, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
228, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
228, /* (68) tcons ::= CHECK LP expr RP onconf */
228, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
231, /* (70) defer_subclause_opt ::= */
216, /* (71) onconf ::= */
216, /* (72) onconf ::= ON CONFLICT resolvetype */
232, /* (73) orconf ::= */
232, /* (74) orconf ::= OR resolvetype */
233, /* (75) resolvetype ::= IGNORE */
233, /* (76) resolvetype ::= REPLACE */
189, /* (77) cmd ::= DROP TABLE ifexists fullname */
235, /* (78) ifexists ::= IF EXISTS */
235, /* (79) ifexists ::= */
189, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
189, /* (81) cmd ::= DROP VIEW ifexists fullname */
189, /* (82) cmd ::= select */
203, /* (83) select ::= WITH wqlist selectnowith */
203, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
203, /* (85) select ::= selectnowith */
237, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
240, /* (87) multiselect_op ::= UNION */
240, /* (88) multiselect_op ::= UNION ALL */
240, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
238, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
238, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
250, /* (92) values ::= VALUES LP nexprlist RP */
250, /* (93) values ::= values COMMA LP nexprlist RP */
241, /* (94) distinct ::= DISTINCT */
241, /* (95) distinct ::= ALL */
241, /* (96) distinct ::= */
252, /* (97) sclp ::= */
242, /* (98) selcollist ::= sclp scanpt expr scanpt as */
242, /* (99) selcollist ::= sclp scanpt STAR */
242, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
253, /* (101) as ::= AS nm */
253, /* (102) as ::= */
243, /* (103) from ::= */
243, /* (104) from ::= FROM seltablist */
255, /* (105) stl_prefix ::= seltablist joinop */
255, /* (106) stl_prefix ::= */
254, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
254, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
254, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
254, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
199, /* (111) dbnm ::= */
199, /* (112) dbnm ::= DOT nm */
236, /* (113) fullname ::= nm */
236, /* (114) fullname ::= nm DOT nm */
261, /* (115) xfullname ::= nm */
261, /* (116) xfullname ::= nm DOT nm */
261, /* (117) xfullname ::= nm DOT nm AS nm */
261, /* (118) xfullname ::= nm AS nm */
256, /* (119) joinop ::= COMMA|JOIN */
256, /* (120) joinop ::= JOIN_KW JOIN */
256, /* (121) joinop ::= JOIN_KW nm JOIN */
256, /* (122) joinop ::= JOIN_KW nm nm JOIN */
258, /* (123) on_opt ::= ON expr */
258, /* (124) on_opt ::= */
257, /* (125) indexed_opt ::= */
257, /* (126) indexed_opt ::= INDEXED BY nm */
257, /* (127) indexed_opt ::= NOT INDEXED */
259, /* (128) using_opt ::= USING LP idlist RP */
259, /* (129) using_opt ::= */
247, /* (130) orderby_opt ::= */
247, /* (131) orderby_opt ::= ORDER BY sortlist */
229, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
229, /* (133) sortlist ::= expr sortorder nulls */
217, /* (134) sortorder ::= ASC */
217, /* (135) sortorder ::= DESC */
217, /* (136) sortorder ::= */
263, /* (137) nulls ::= NULLS FIRST */
263, /* (138) nulls ::= NULLS LAST */
263, /* (139) nulls ::= */
245, /* (140) groupby_opt ::= */
245, /* (141) groupby_opt ::= GROUP BY nexprlist */
246, /* (142) having_opt ::= */
246, /* (143) having_opt ::= HAVING expr */
248, /* (144) limit_opt ::= */
248, /* (145) limit_opt ::= LIMIT expr */
248, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
248, /* (147) limit_opt ::= LIMIT expr COMMA expr */
189, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
244, /* (149) where_opt ::= */
244, /* (150) where_opt ::= WHERE expr */
265, /* (151) where_opt_ret ::= */
265, /* (152) where_opt_ret ::= WHERE expr */
265, /* (153) where_opt_ret ::= RETURNING selcollist */
265, /* (154) where_opt_ret ::= WHERE expr RETURNING selcollist */
189, /* (155) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
266, /* (156) setlist ::= setlist COMMA nm EQ expr */
266, /* (157) setlist ::= setlist COMMA LP idlist RP EQ expr */
266, /* (158) setlist ::= nm EQ expr */
266, /* (159) setlist ::= LP idlist RP EQ expr */
189, /* (160) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
189, /* (161) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
269, /* (162) upsert ::= */
269, /* (163) upsert ::= RETURNING selcollist */
269, /* (164) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
269, /* (165) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
269, /* (166) upsert ::= ON CONFLICT DO NOTHING returning */
269, /* (167) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
270, /* (168) returning ::= RETURNING selcollist */
267, /* (169) insert_cmd ::= INSERT orconf */
267, /* (170) insert_cmd ::= REPLACE */
268, /* (171) idlist_opt ::= */
268, /* (172) idlist_opt ::= LP idlist RP */
262, /* (173) idlist ::= idlist COMMA nm */
262, /* (174) idlist ::= nm */
215, /* (175) expr ::= LP expr RP */
215, /* (176) expr ::= ID|INDEXED */
215, /* (177) expr ::= JOIN_KW */
215, /* (178) expr ::= nm DOT nm */
215, /* (179) expr ::= nm DOT nm DOT nm */
214, /* (180) term ::= NULL|FLOAT|BLOB */
214, /* (181) term ::= STRING */
214, /* (182) term ::= INTEGER */
215, /* (183) expr ::= VARIABLE */
215, /* (184) expr ::= expr COLLATE ID|STRING */
215, /* (185) expr ::= CAST LP expr AS typetoken RP */
215, /* (186) expr ::= ID|INDEXED LP distinct exprlist RP */
215, /* (187) expr ::= ID|INDEXED LP STAR RP */
215, /* (188) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
215, /* (189) expr ::= ID|INDEXED LP STAR RP filter_over */
214, /* (190) term ::= CTIME_KW */
215, /* (191) expr ::= LP nexprlist COMMA expr RP */
215, /* (192) expr ::= expr AND expr */
215, /* (193) expr ::= expr OR expr */
215, /* (194) expr ::= expr LT|GT|GE|LE expr */
215, /* (195) expr ::= expr EQ|NE expr */
215, /* (196) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
215, /* (197) expr ::= expr PLUS|MINUS expr */
215, /* (198) expr ::= expr STAR|SLASH|REM expr */
215, /* (199) expr ::= expr CONCAT expr */
272, /* (200) likeop ::= NOT LIKE_KW|MATCH */
215, /* (201) expr ::= expr likeop expr */
215, /* (202) expr ::= expr likeop expr ESCAPE expr */
215, /* (203) expr ::= expr ISNULL|NOTNULL */
215, /* (204) expr ::= expr NOT NULL */
215, /* (205) expr ::= expr IS expr */
215, /* (206) expr ::= expr IS NOT expr */
215, /* (207) expr ::= NOT expr */
215, /* (208) expr ::= BITNOT expr */
215, /* (209) expr ::= PLUS|MINUS expr */
273, /* (210) between_op ::= BETWEEN */
273, /* (211) between_op ::= NOT BETWEEN */
215, /* (212) expr ::= expr between_op expr AND expr */
274, /* (213) in_op ::= IN */
274, /* (214) in_op ::= NOT IN */
215, /* (215) expr ::= expr in_op LP exprlist RP */
215, /* (216) expr ::= LP select RP */
215, /* (217) expr ::= expr in_op LP select RP */
215, /* (218) expr ::= expr in_op nm dbnm paren_exprlist */
215, /* (219) expr ::= EXISTS LP select RP */
215, /* (220) expr ::= CASE case_operand case_exprlist case_else END */
277, /* (221) case_exprlist ::= case_exprlist WHEN expr THEN expr */
277, /* (222) case_exprlist ::= WHEN expr THEN expr */
278, /* (223) case_else ::= ELSE expr */
278, /* (224) case_else ::= */
276, /* (225) case_operand ::= expr */
276, /* (226) case_operand ::= */
260, /* (227) exprlist ::= */
251, /* (228) nexprlist ::= nexprlist COMMA expr */
251, /* (229) nexprlist ::= expr */
275, /* (230) paren_exprlist ::= */
275, /* (231) paren_exprlist ::= LP exprlist RP */
189, /* (232) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
279, /* (233) uniqueflag ::= UNIQUE */
279, /* (234) uniqueflag ::= */
219, /* (235) eidlist_opt ::= */
219, /* (236) eidlist_opt ::= LP eidlist RP */
230, /* (237) eidlist ::= eidlist COMMA nm collate sortorder */
230, /* (238) eidlist ::= nm collate sortorder */
280, /* (239) collate ::= */
280, /* (240) collate ::= COLLATE ID|STRING */
189, /* (241) cmd ::= DROP INDEX ifexists fullname */
189, /* (242) cmd ::= VACUUM vinto */
189, /* (243) cmd ::= VACUUM nm vinto */
281, /* (244) vinto ::= INTO expr */
281, /* (245) vinto ::= */
189, /* (246) cmd ::= PRAGMA nm dbnm */
189, /* (247) cmd ::= PRAGMA nm dbnm EQ nmnum */
189, /* (248) cmd ::= PRAGMA nm dbnm LP nmnum RP */
189, /* (249) cmd ::= PRAGMA nm dbnm EQ minus_num */
189, /* (250) cmd ::= PRAGMA nm dbnm LP minus_num RP */
209, /* (251) plus_num ::= PLUS INTEGER|FLOAT */
210, /* (252) minus_num ::= MINUS INTEGER|FLOAT */
189, /* (253) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
283, /* (254) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
285, /* (255) trigger_time ::= BEFORE|AFTER */
285, /* (256) trigger_time ::= INSTEAD OF */
285, /* (257) trigger_time ::= */
286, /* (258) trigger_event ::= DELETE|INSERT */
286, /* (259) trigger_event ::= UPDATE */
286, /* (260) trigger_event ::= UPDATE OF idlist */
288, /* (261) when_clause ::= */
288, /* (262) when_clause ::= WHEN expr */
284, /* (263) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
284, /* (264) trigger_cmd_list ::= trigger_cmd SEMI */
290, /* (265) trnm ::= nm DOT nm */
291, /* (266) tridxby ::= INDEXED BY nm */
291, /* (267) tridxby ::= NOT INDEXED */
289, /* (268) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
289, /* (269) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
289, /* (270) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
289, /* (271) trigger_cmd ::= scanpt select scanpt */
215, /* (272) expr ::= RAISE LP IGNORE RP */
215, /* (273) expr ::= RAISE LP raisetype COMMA nm RP */
234, /* (274) raisetype ::= ROLLBACK */
234, /* (275) raisetype ::= ABORT */
234, /* (276) raisetype ::= FAIL */
189, /* (277) cmd ::= DROP TRIGGER ifexists fullname */
189, /* (278) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
189, /* (279) cmd ::= DETACH database_kw_opt expr */
293, /* (280) key_opt ::= */
293, /* (281) key_opt ::= KEY expr */
189, /* (282) cmd ::= REINDEX */
189, /* (283) cmd ::= REINDEX nm dbnm */
189, /* (284) cmd ::= ANALYZE */
189, /* (285) cmd ::= ANALYZE nm dbnm */
189, /* (286) cmd ::= ALTER TABLE fullname RENAME TO nm */
189, /* (287) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
189, /* (288) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
294, /* (289) add_column_fullname ::= fullname */
189, /* (290) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
189, /* (291) cmd ::= create_vtab */
189, /* (292) cmd ::= create_vtab LP vtabarglist RP */
296, /* (293) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
298, /* (294) vtabarg ::= */
299, /* (295) vtabargtoken ::= ANY */
299, /* (296) vtabargtoken ::= lp anylist RP */
300, /* (297) lp ::= LP */
264, /* (298) with ::= WITH wqlist */
264, /* (299) with ::= WITH RECURSIVE wqlist */
303, /* (300) wqas ::= AS */
303, /* (301) wqas ::= AS MATERIALIZED */
303, /* (302) wqas ::= AS NOT MATERIALIZED */
302, /* (303) wqitem ::= nm eidlist_opt wqas LP select RP */
239, /* (304) wqlist ::= wqitem */
239, /* (305) wqlist ::= wqlist COMMA wqitem */
304, /* (306) windowdefn_list ::= windowdefn */
304, /* (307) windowdefn_list ::= windowdefn_list COMMA windowdefn */
305, /* (308) windowdefn ::= nm AS LP window RP */
306, /* (309) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
306, /* (310) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
306, /* (311) window ::= ORDER BY sortlist frame_opt */
306, /* (312) window ::= nm ORDER BY sortlist frame_opt */
306, /* (313) window ::= frame_opt */
306, /* (314) window ::= nm frame_opt */
307, /* (315) frame_opt ::= */
307, /* (316) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
307, /* (317) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
311, /* (318) range_or_rows ::= RANGE|ROWS|GROUPS */
313, /* (319) frame_bound_s ::= frame_bound */
313, /* (320) frame_bound_s ::= UNBOUNDED PRECEDING */
314, /* (321) frame_bound_e ::= frame_bound */
314, /* (322) frame_bound_e ::= UNBOUNDED FOLLOWING */
312, /* (323) frame_bound ::= expr PRECEDING|FOLLOWING */
312, /* (324) frame_bound ::= CURRENT ROW */
315, /* (325) frame_exclude_opt ::= */
315, /* (326) frame_exclude_opt ::= EXCLUDE frame_exclude */
316, /* (327) frame_exclude ::= NO OTHERS */
316, /* (328) frame_exclude ::= CURRENT ROW */
316, /* (329) frame_exclude ::= GROUP|TIES */
249, /* (330) window_clause ::= WINDOW windowdefn_list */
271, /* (331) filter_over ::= filter_clause over_clause */
271, /* (332) filter_over ::= over_clause */
271, /* (333) filter_over ::= filter_clause */
310, /* (334) over_clause ::= OVER LP window RP */
310, /* (335) over_clause ::= OVER nm */
309, /* (336) filter_clause ::= FILTER LP WHERE expr RP */
184, /* (337) input ::= cmdlist */
185, /* (338) cmdlist ::= cmdlist ecmd */
185, /* (339) cmdlist ::= ecmd */
186, /* (340) ecmd ::= SEMI */
186, /* (341) ecmd ::= cmdx SEMI */
186, /* (342) ecmd ::= explain cmdx SEMI */
191, /* (343) trans_opt ::= */
191, /* (344) trans_opt ::= TRANSACTION */
191, /* (345) trans_opt ::= TRANSACTION nm */
193, /* (346) savepoint_opt ::= SAVEPOINT */
193, /* (347) savepoint_opt ::= */
189, /* (348) cmd ::= create_table create_table_args */
200, /* (349) columnlist ::= columnlist COMMA columnname carglist */
200, /* (350) columnlist ::= columnname carglist */
192, /* (351) nm ::= ID|INDEXED */
192, /* (352) nm ::= STRING */
192, /* (353) nm ::= JOIN_KW */
206, /* (354) typetoken ::= typename */
207, /* (355) typename ::= ID|STRING */
208, /* (356) signed ::= plus_num */
208, /* (357) signed ::= minus_num */
205, /* (358) carglist ::= carglist ccons */
205, /* (359) carglist ::= */
213, /* (360) ccons ::= NULL onconf */
213, /* (361) ccons ::= GENERATED ALWAYS AS generated */
213, /* (362) ccons ::= AS generated */
201, /* (363) conslist_opt ::= COMMA conslist */
226, /* (364) conslist ::= conslist tconscomma tcons */
226, /* (365) conslist ::= tcons */
227, /* (366) tconscomma ::= */
231, /* (367) defer_subclause_opt ::= defer_subclause */
233, /* (368) resolvetype ::= raisetype */
237, /* (369) selectnowith ::= oneselect */
238, /* (370) oneselect ::= values */
252, /* (371) sclp ::= selcollist COMMA */
253, /* (372) as ::= ID|STRING */
270, /* (373) returning ::= */
215, /* (374) expr ::= term */
272, /* (375) likeop ::= LIKE_KW|MATCH */
260, /* (376) exprlist ::= nexprlist */
282, /* (377) nmnum ::= plus_num */
282, /* (378) nmnum ::= nm */
282, /* (379) nmnum ::= ON */
282, /* (380) nmnum ::= DELETE */
282, /* (381) nmnum ::= DEFAULT */
209, /* (382) plus_num ::= INTEGER|FLOAT */
287, /* (383) foreach_clause ::= */
287, /* (384) foreach_clause ::= FOR EACH ROW */
290, /* (385) trnm ::= nm */
291, /* (386) tridxby ::= */
292, /* (387) database_kw_opt ::= DATABASE */
292, /* (388) database_kw_opt ::= */
295, /* (389) kwcolumn_opt ::= */
295, /* (390) kwcolumn_opt ::= COLUMNKW */
297, /* (391) vtabarglist ::= vtabarg */
297, /* (392) vtabarglist ::= vtabarglist COMMA vtabarg */
298, /* (393) vtabarg ::= vtabarg vtabargtoken */
301, /* (394) anylist ::= */
301, /* (395) anylist ::= anylist LP anylist RP */
301, /* (396) anylist ::= anylist ANY */
264, /* (397) with ::= */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = {
-1, /* (0) explain ::= EXPLAIN */
-3, /* (1) explain ::= EXPLAIN QUERY PLAN */
|
| ︙ | ︙ | |||
160484 160485 160486 160487 160488 160489 160490 |
case 1: /* explain ::= EXPLAIN QUERY PLAN */
{ pParse->explain = 2; }
break;
case 2: /* cmdx ::= cmd */
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
| | | | | 161475 161476 161477 161478 161479 161480 161481 161482 161483 161484 161485 161486 161487 161488 161489 161490 161491 161492 161493 161494 161495 161496 161497 161498 |
case 1: /* explain ::= EXPLAIN QUERY PLAN */
{ pParse->explain = 2; }
break;
case 2: /* cmdx ::= cmd */
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy376);}
break;
case 4: /* transtype ::= */
{yymsp[1].minor.yy376 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
case 318: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==318);
{yymsp[0].minor.yy376 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
{sqlite3EndTransaction(pParse,yymsp[-1].major);}
break;
case 10: /* cmd ::= SAVEPOINT nm */
{
|
| ︙ | ︙ | |||
160516 160517 160518 160519 160520 160521 160522 |
case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
| | | | < | | | | | | | 161507 161508 161509 161510 161511 161512 161513 161514 161515 161516 161517 161518 161519 161520 161521 161522 161523 161524 161525 161526 161527 161528 161529 161530 161531 161532 161533 161534 161535 161536 161537 161538 161539 161540 161541 161542 161543 161544 161545 161546 161547 161548 161549 161550 161551 161552 161553 161554 161555 161556 161557 161558 161559 161560 |
case 12: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy376,0,0,yymsp[-2].minor.yy376);
}
break;
case 14: /* createkw ::= CREATE */
{disableLookaside(pParse);}
break;
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
case 21: /* table_options ::= */ yytestcase(yyruleno==21);
case 45: /* autoinc ::= */ yytestcase(yyruleno==45);
case 60: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==60);
case 70: /* defer_subclause_opt ::= */ yytestcase(yyruleno==70);
case 79: /* ifexists ::= */ yytestcase(yyruleno==79);
case 96: /* distinct ::= */ yytestcase(yyruleno==96);
case 239: /* collate ::= */ yytestcase(yyruleno==239);
{yymsp[1].minor.yy376 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
{yymsp[-2].minor.yy376 = 1;}
break;
case 17: /* temp ::= TEMP */
{yymsp[0].minor.yy376 = pParse->db->init.busy==0;}
break;
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy376,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy81);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy81);
}
break;
case 22: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
yymsp[-1].minor.yy376 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
yymsp[-1].minor.yy376 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
break;
case 23: /* columnname ::= nm typetoken */
{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
|
| ︙ | ︙ | |||
160585 160586 160587 160588 160589 160590 160591 |
break;
case 27: /* typename ::= typename ID|STRING */
{yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
case 28: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
| | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 161575 161576 161577 161578 161579 161580 161581 161582 161583 161584 161585 161586 161587 161588 161589 161590 161591 161592 161593 161594 161595 161596 161597 161598 161599 161600 161601 161602 161603 161604 161605 161606 161607 161608 161609 161610 161611 161612 161613 161614 161615 161616 161617 161618 161619 161620 161621 161622 161623 161624 161625 161626 161627 161628 161629 161630 161631 161632 161633 161634 161635 161636 161637 161638 161639 161640 161641 161642 161643 161644 161645 161646 161647 161648 161649 161650 161651 161652 161653 161654 161655 161656 161657 161658 161659 161660 161661 161662 161663 161664 161665 161666 161667 161668 161669 161670 161671 161672 161673 161674 161675 161676 161677 161678 161679 161680 161681 161682 161683 161684 161685 161686 161687 161688 161689 161690 161691 161692 161693 161694 161695 161696 161697 161698 161699 161700 161701 161702 161703 161704 161705 161706 161707 161708 161709 161710 161711 161712 161713 161714 161715 161716 161717 161718 161719 161720 161721 161722 161723 161724 161725 161726 161727 161728 161729 161730 161731 161732 161733 161734 161735 161736 161737 161738 161739 161740 161741 161742 161743 161744 161745 161746 161747 161748 161749 161750 161751 161752 161753 161754 161755 161756 161757 161758 161759 161760 161761 161762 161763 161764 161765 161766 161767 161768 161769 161770 161771 161772 161773 161774 161775 161776 161777 161778 161779 161780 161781 161782 161783 161784 161785 161786 161787 161788 161789 161790 161791 161792 161793 161794 161795 161796 161797 161798 161799 161800 161801 161802 161803 161804 161805 161806 161807 161808 161809 161810 161811 161812 161813 161814 161815 161816 161817 161818 161819 161820 161821 161822 161823 161824 161825 161826 161827 161828 161829 161830 161831 161832 161833 161834 161835 161836 161837 161838 161839 161840 161841 161842 161843 161844 161845 161846 161847 161848 161849 161850 161851 161852 161853 161854 161855 161856 161857 161858 161859 161860 161861 161862 161863 161864 161865 161866 161867 161868 161869 161870 161871 161872 161873 161874 161875 161876 161877 161878 161879 161880 161881 161882 161883 161884 161885 161886 161887 161888 161889 161890 161891 161892 161893 161894 161895 161896 161897 161898 161899 161900 161901 161902 161903 161904 161905 161906 161907 161908 161909 161910 161911 161912 161913 161914 161915 161916 161917 161918 161919 161920 161921 161922 161923 161924 161925 161926 161927 161928 161929 161930 161931 161932 161933 161934 161935 161936 161937 161938 161939 161940 161941 161942 161943 161944 161945 161946 161947 161948 161949 161950 161951 161952 161953 161954 161955 161956 161957 161958 161959 161960 161961 161962 161963 161964 161965 161966 161967 161968 161969 161970 161971 161972 161973 161974 161975 161976 161977 161978 161979 161980 161981 161982 161983 161984 161985 161986 161987 161988 161989 161990 161991 161992 161993 161994 161995 161996 161997 161998 161999 162000 162001 162002 162003 162004 162005 162006 162007 162008 162009 162010 162011 162012 162013 162014 162015 162016 162017 162018 162019 162020 162021 162022 162023 162024 162025 162026 162027 162028 162029 162030 162031 162032 162033 162034 162035 162036 162037 162038 162039 162040 162041 162042 162043 162044 162045 162046 162047 162048 162049 162050 162051 162052 162053 162054 162055 162056 162057 162058 162059 162060 162061 162062 162063 162064 162065 162066 162067 162068 162069 162070 162071 162072 162073 162074 162075 162076 162077 162078 162079 162080 162081 162082 162083 162084 162085 162086 162087 162088 162089 162090 162091 162092 162093 162094 162095 162096 162097 162098 162099 162100 162101 162102 162103 162104 162105 162106 162107 162108 162109 162110 162111 162112 162113 162114 162115 162116 162117 162118 162119 162120 162121 162122 162123 162124 162125 162126 162127 162128 162129 162130 162131 162132 162133 162134 162135 162136 162137 162138 162139 162140 162141 162142 162143 162144 162145 162146 162147 162148 162149 162150 162151 162152 162153 162154 162155 162156 162157 162158 162159 162160 162161 162162 162163 162164 162165 162166 162167 162168 162169 162170 162171 162172 162173 162174 162175 162176 162177 162178 162179 162180 162181 162182 162183 162184 162185 162186 162187 162188 162189 162190 162191 162192 162193 162194 162195 162196 162197 162198 162199 162200 162201 162202 162203 162204 162205 162206 162207 162208 162209 162210 162211 162212 162213 162214 162215 162216 162217 162218 162219 162220 162221 162222 162223 162224 162225 162226 162227 162228 162229 162230 162231 162232 162233 162234 162235 162236 162237 162238 162239 162240 162241 162242 162243 162244 162245 162246 162247 162248 162249 162250 162251 162252 162253 162254 162255 162256 162257 162258 162259 162260 162261 162262 162263 162264 162265 162266 162267 162268 162269 162270 162271 162272 162273 162274 162275 162276 162277 162278 162279 162280 162281 162282 162283 162284 162285 162286 162287 162288 162289 162290 162291 162292 162293 162294 162295 162296 162297 162298 162299 162300 162301 162302 162303 162304 162305 162306 162307 162308 162309 162310 162311 162312 162313 162314 162315 162316 162317 162318 162319 162320 162321 162322 162323 162324 162325 162326 162327 162328 162329 162330 162331 162332 162333 162334 162335 162336 162337 162338 162339 162340 162341 162342 162343 162344 162345 162346 162347 162348 162349 162350 162351 162352 162353 162354 162355 162356 162357 162358 162359 162360 162361 162362 162363 162364 162365 162366 162367 162368 162369 162370 162371 162372 162373 162374 162375 162376 162377 162378 162379 162380 162381 162382 162383 162384 162385 162386 162387 162388 162389 162390 162391 162392 162393 162394 162395 162396 162397 162398 162399 162400 162401 162402 162403 162404 162405 162406 162407 162408 162409 162410 162411 162412 162413 162414 162415 162416 162417 162418 162419 162420 162421 162422 162423 162424 162425 162426 162427 162428 162429 162430 162431 162432 162433 162434 162435 162436 162437 162438 162439 162440 162441 162442 162443 162444 162445 162446 162447 162448 162449 162450 162451 162452 162453 162454 162455 162456 162457 162458 162459 162460 162461 162462 162463 162464 162465 162466 162467 162468 162469 162470 162471 162472 162473 162474 162475 162476 162477 162478 162479 162480 162481 162482 162483 162484 162485 162486 162487 162488 162489 162490 |
break;
case 27: /* typename ::= typename ID|STRING */
{yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
case 28: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
yymsp[1].minor.yy504 = yyLookaheadToken.z;
}
break;
case 29: /* scantok ::= */
{
assert( yyLookahead!=YYNOCODE );
yymsp[1].minor.yy0 = yyLookaheadToken;
}
break;
case 30: /* ccons ::= CONSTRAINT nm */
case 65: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==65);
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
case 31: /* ccons ::= DEFAULT scantok term */
{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy404,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 32: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy404,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 33: /* ccons ::= DEFAULT PLUS scantok term */
{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy404,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 34: /* ccons ::= DEFAULT MINUS scantok term */
{
Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy404, 0);
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
case 35: /* ccons ::= DEFAULT scantok ID|INDEXED */
{
Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0);
if( p ){
sqlite3ExprIdToTrueFalse(p);
testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
}
sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n);
}
break;
case 36: /* ccons ::= NOT NULL onconf */
{sqlite3AddNotNull(pParse, yymsp[0].minor.yy376);}
break;
case 37: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy376,yymsp[0].minor.yy376,yymsp[-2].minor.yy376);}
break;
case 38: /* ccons ::= UNIQUE onconf */
{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy376,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 39: /* ccons ::= CHECK LP expr RP */
{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy404,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 40: /* ccons ::= REFERENCES nm eidlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy70,yymsp[0].minor.yy376);}
break;
case 41: /* ccons ::= defer_subclause */
{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy376);}
break;
case 42: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 43: /* generated ::= LP expr RP */
{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy404,0);}
break;
case 44: /* generated ::= LP expr RP ID */
{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy404,&yymsp[0].minor.yy0);}
break;
case 46: /* autoinc ::= AUTOINCR */
{yymsp[0].minor.yy376 = 1;}
break;
case 47: /* refargs ::= */
{ yymsp[1].minor.yy376 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 48: /* refargs ::= refargs refarg */
{ yymsp[-1].minor.yy376 = (yymsp[-1].minor.yy376 & ~yymsp[0].minor.yy139.mask) | yymsp[0].minor.yy139.value; }
break;
case 49: /* refarg ::= MATCH nm */
{ yymsp[-1].minor.yy139.value = 0; yymsp[-1].minor.yy139.mask = 0x000000; }
break;
case 50: /* refarg ::= ON INSERT refact */
{ yymsp[-2].minor.yy139.value = 0; yymsp[-2].minor.yy139.mask = 0x000000; }
break;
case 51: /* refarg ::= ON DELETE refact */
{ yymsp[-2].minor.yy139.value = yymsp[0].minor.yy376; yymsp[-2].minor.yy139.mask = 0x0000ff; }
break;
case 52: /* refarg ::= ON UPDATE refact */
{ yymsp[-2].minor.yy139.value = yymsp[0].minor.yy376<<8; yymsp[-2].minor.yy139.mask = 0x00ff00; }
break;
case 53: /* refact ::= SET NULL */
{ yymsp[-1].minor.yy376 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 54: /* refact ::= SET DEFAULT */
{ yymsp[-1].minor.yy376 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 55: /* refact ::= CASCADE */
{ yymsp[0].minor.yy376 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 56: /* refact ::= RESTRICT */
{ yymsp[0].minor.yy376 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 57: /* refact ::= NO ACTION */
{ yymsp[-1].minor.yy376 = OE_None; /* EV: R-33326-45252 */}
break;
case 58: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
{yymsp[-2].minor.yy376 = 0;}
break;
case 59: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 74: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==74);
case 169: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==169);
{yymsp[-1].minor.yy376 = yymsp[0].minor.yy376;}
break;
case 61: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 78: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==78);
case 211: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==211);
case 214: /* in_op ::= NOT IN */ yytestcase(yyruleno==214);
case 240: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==240);
{yymsp[-1].minor.yy376 = 1;}
break;
case 62: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
{yymsp[-1].minor.yy376 = 0;}
break;
case 64: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
case 66: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy70,yymsp[0].minor.yy376,yymsp[-2].minor.yy376,0);}
break;
case 67: /* tcons ::= UNIQUE LP sortlist RP onconf */
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy70,yymsp[0].minor.yy376,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 68: /* tcons ::= CHECK LP expr RP onconf */
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy404,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 69: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy70, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy70, yymsp[-1].minor.yy376);
sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy376);
}
break;
case 71: /* onconf ::= */
case 73: /* orconf ::= */ yytestcase(yyruleno==73);
{yymsp[1].minor.yy376 = OE_Default;}
break;
case 72: /* onconf ::= ON CONFLICT resolvetype */
{yymsp[-2].minor.yy376 = yymsp[0].minor.yy376;}
break;
case 75: /* resolvetype ::= IGNORE */
{yymsp[0].minor.yy376 = OE_Ignore;}
break;
case 76: /* resolvetype ::= REPLACE */
case 170: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==170);
{yymsp[0].minor.yy376 = OE_Replace;}
break;
case 77: /* cmd ::= DROP TABLE ifexists fullname */
{
sqlite3DropTable(pParse, yymsp[0].minor.yy153, 0, yymsp[-1].minor.yy376);
}
break;
case 80: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy70, yymsp[0].minor.yy81, yymsp[-7].minor.yy376, yymsp[-5].minor.yy376);
}
break;
case 81: /* cmd ::= DROP VIEW ifexists fullname */
{
sqlite3DropTable(pParse, yymsp[0].minor.yy153, 1, yymsp[-1].minor.yy376);
}
break;
case 82: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
sqlite3Select(pParse, yymsp[0].minor.yy81, &dest);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy81);
}
break;
case 83: /* select ::= WITH wqlist selectnowith */
{yymsp[-2].minor.yy81 = attachWithToSelect(pParse,yymsp[0].minor.yy81,yymsp[-1].minor.yy103);}
break;
case 84: /* select ::= WITH RECURSIVE wqlist selectnowith */
{yymsp[-3].minor.yy81 = attachWithToSelect(pParse,yymsp[0].minor.yy81,yymsp[-1].minor.yy103);}
break;
case 85: /* select ::= selectnowith */
{
Select *p = yymsp[0].minor.yy81;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
yymsp[0].minor.yy81 = p; /*A-overwrites-X*/
}
break;
case 86: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
Select *pRhs = yymsp[0].minor.yy81;
Select *pLhs = yymsp[-2].minor.yy81;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
pRhs->op = (u8)yymsp[-1].minor.yy376;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
if( yymsp[-1].minor.yy376!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
yymsp[-2].minor.yy81 = pRhs;
}
break;
case 87: /* multiselect_op ::= UNION */
case 89: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==89);
{yymsp[0].minor.yy376 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 88: /* multiselect_op ::= UNION ALL */
{yymsp[-1].minor.yy376 = TK_ALL;}
break;
case 90: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
yymsp[-8].minor.yy81 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy70,yymsp[-5].minor.yy153,yymsp[-4].minor.yy404,yymsp[-3].minor.yy70,yymsp[-2].minor.yy404,yymsp[-1].minor.yy70,yymsp[-7].minor.yy376,yymsp[0].minor.yy404);
}
break;
case 91: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
{
yymsp[-9].minor.yy81 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy70,yymsp[-6].minor.yy153,yymsp[-5].minor.yy404,yymsp[-4].minor.yy70,yymsp[-3].minor.yy404,yymsp[-1].minor.yy70,yymsp[-8].minor.yy376,yymsp[0].minor.yy404);
if( yymsp[-9].minor.yy81 ){
yymsp[-9].minor.yy81->pWinDefn = yymsp[-2].minor.yy49;
}else{
sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy49);
}
}
break;
case 92: /* values ::= VALUES LP nexprlist RP */
{
yymsp[-3].minor.yy81 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy70,0,0,0,0,0,SF_Values,0);
}
break;
case 93: /* values ::= values COMMA LP nexprlist RP */
{
Select *pRight, *pLeft = yymsp[-4].minor.yy81;
pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy70,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
yymsp[-4].minor.yy81 = pRight;
}else{
yymsp[-4].minor.yy81 = pLeft;
}
}
break;
case 94: /* distinct ::= DISTINCT */
{yymsp[0].minor.yy376 = SF_Distinct;}
break;
case 95: /* distinct ::= ALL */
{yymsp[0].minor.yy376 = SF_All;}
break;
case 97: /* sclp ::= */
case 130: /* orderby_opt ::= */ yytestcase(yyruleno==130);
case 140: /* groupby_opt ::= */ yytestcase(yyruleno==140);
case 227: /* exprlist ::= */ yytestcase(yyruleno==227);
case 230: /* paren_exprlist ::= */ yytestcase(yyruleno==230);
case 235: /* eidlist_opt ::= */ yytestcase(yyruleno==235);
{yymsp[1].minor.yy70 = 0;}
break;
case 98: /* selcollist ::= sclp scanpt expr scanpt as */
{
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy70, yymsp[-2].minor.yy404);
if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy70, &yymsp[0].minor.yy0, 1);
sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy70,yymsp[-3].minor.yy504,yymsp[-1].minor.yy504);
}
break;
case 99: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
yymsp[-2].minor.yy70 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy70, p);
}
break;
case 100: /* selcollist ::= sclp scanpt nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy70, pDot);
}
break;
case 101: /* as ::= AS nm */
case 112: /* dbnm ::= DOT nm */ yytestcase(yyruleno==112);
case 251: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==251);
case 252: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==252);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 103: /* from ::= */
case 106: /* stl_prefix ::= */ yytestcase(yyruleno==106);
{yymsp[1].minor.yy153 = 0;}
break;
case 104: /* from ::= FROM seltablist */
{
yymsp[-1].minor.yy153 = yymsp[0].minor.yy153;
sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy153);
}
break;
case 105: /* stl_prefix ::= seltablist joinop */
{
if( ALWAYS(yymsp[-1].minor.yy153 && yymsp[-1].minor.yy153->nSrc>0) ) yymsp[-1].minor.yy153->a[yymsp[-1].minor.yy153->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy376;
}
break;
case 107: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
yymsp[-6].minor.yy153 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy153,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy404,yymsp[0].minor.yy436);
sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy153, &yymsp[-2].minor.yy0);
}
break;
case 108: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
yymsp[-8].minor.yy153 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy153,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy404,yymsp[0].minor.yy436);
sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy153, yymsp[-4].minor.yy70);
}
break;
case 109: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
yymsp[-6].minor.yy153 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy153,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy81,yymsp[-1].minor.yy404,yymsp[0].minor.yy436);
}
break;
case 110: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
if( yymsp[-6].minor.yy153==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy404==0 && yymsp[0].minor.yy436==0 ){
yymsp[-6].minor.yy153 = yymsp[-4].minor.yy153;
}else if( yymsp[-4].minor.yy153->nSrc==1 ){
yymsp[-6].minor.yy153 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy153,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy404,yymsp[0].minor.yy436);
if( yymsp[-6].minor.yy153 ){
SrcItem *pNew = &yymsp[-6].minor.yy153->a[yymsp[-6].minor.yy153->nSrc-1];
SrcItem *pOld = yymsp[-4].minor.yy153->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy153);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy153);
pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy153,0,0,0,0,SF_NestedFrom,0);
yymsp[-6].minor.yy153 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy153,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy404,yymsp[0].minor.yy436);
}
}
break;
case 111: /* dbnm ::= */
case 125: /* indexed_opt ::= */ yytestcase(yyruleno==125);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
case 113: /* fullname ::= nm */
{
yylhsminor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
if( IN_RENAME_OBJECT && yylhsminor.yy153 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy153->a[0].zName, &yymsp[0].minor.yy0);
}
yymsp[0].minor.yy153 = yylhsminor.yy153;
break;
case 114: /* fullname ::= nm DOT nm */
{
yylhsminor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
if( IN_RENAME_OBJECT && yylhsminor.yy153 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy153->a[0].zName, &yymsp[0].minor.yy0);
}
yymsp[-2].minor.yy153 = yylhsminor.yy153;
break;
case 115: /* xfullname ::= nm */
{yymsp[0].minor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
case 116: /* xfullname ::= nm DOT nm */
{yymsp[-2].minor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 117: /* xfullname ::= nm DOT nm AS nm */
{
yymsp[-4].minor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
if( yymsp[-4].minor.yy153 ) yymsp[-4].minor.yy153->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 118: /* xfullname ::= nm AS nm */
{
yymsp[-2].minor.yy153 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
if( yymsp[-2].minor.yy153 ) yymsp[-2].minor.yy153->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 119: /* joinop ::= COMMA|JOIN */
{ yymsp[0].minor.yy376 = JT_INNER; }
break;
case 120: /* joinop ::= JOIN_KW JOIN */
{yymsp[-1].minor.yy376 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 121: /* joinop ::= JOIN_KW nm JOIN */
{yymsp[-2].minor.yy376 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 122: /* joinop ::= JOIN_KW nm nm JOIN */
{yymsp[-3].minor.yy376 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 123: /* on_opt ::= ON expr */
case 143: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==143);
case 150: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==150);
case 152: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==152);
case 223: /* case_else ::= ELSE expr */ yytestcase(yyruleno==223);
case 244: /* vinto ::= INTO expr */ yytestcase(yyruleno==244);
{yymsp[-1].minor.yy404 = yymsp[0].minor.yy404;}
break;
case 124: /* on_opt ::= */
case 142: /* having_opt ::= */ yytestcase(yyruleno==142);
case 144: /* limit_opt ::= */ yytestcase(yyruleno==144);
case 149: /* where_opt ::= */ yytestcase(yyruleno==149);
case 151: /* where_opt_ret ::= */ yytestcase(yyruleno==151);
case 224: /* case_else ::= */ yytestcase(yyruleno==224);
case 226: /* case_operand ::= */ yytestcase(yyruleno==226);
case 245: /* vinto ::= */ yytestcase(yyruleno==245);
{yymsp[1].minor.yy404 = 0;}
break;
case 126: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 127: /* indexed_opt ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
case 128: /* using_opt ::= USING LP idlist RP */
{yymsp[-3].minor.yy436 = yymsp[-1].minor.yy436;}
break;
case 129: /* using_opt ::= */
case 171: /* idlist_opt ::= */ yytestcase(yyruleno==171);
{yymsp[1].minor.yy436 = 0;}
break;
case 131: /* orderby_opt ::= ORDER BY sortlist */
case 141: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==141);
{yymsp[-2].minor.yy70 = yymsp[0].minor.yy70;}
break;
case 132: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy70,yymsp[-2].minor.yy404);
sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy70,yymsp[-1].minor.yy376,yymsp[0].minor.yy376);
}
break;
case 133: /* sortlist ::= expr sortorder nulls */
{
yymsp[-2].minor.yy70 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy404); /*A-overwrites-Y*/
sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy70,yymsp[-1].minor.yy376,yymsp[0].minor.yy376);
}
break;
case 134: /* sortorder ::= ASC */
{yymsp[0].minor.yy376 = SQLITE_SO_ASC;}
break;
case 135: /* sortorder ::= DESC */
{yymsp[0].minor.yy376 = SQLITE_SO_DESC;}
break;
case 136: /* sortorder ::= */
case 139: /* nulls ::= */ yytestcase(yyruleno==139);
{yymsp[1].minor.yy376 = SQLITE_SO_UNDEFINED;}
break;
case 137: /* nulls ::= NULLS FIRST */
{yymsp[-1].minor.yy376 = SQLITE_SO_ASC;}
break;
case 138: /* nulls ::= NULLS LAST */
{yymsp[-1].minor.yy376 = SQLITE_SO_DESC;}
break;
case 145: /* limit_opt ::= LIMIT expr */
{yymsp[-1].minor.yy404 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy404,0);}
break;
case 146: /* limit_opt ::= LIMIT expr OFFSET expr */
{yymsp[-3].minor.yy404 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy404,yymsp[0].minor.yy404);}
break;
case 147: /* limit_opt ::= LIMIT expr COMMA expr */
{yymsp[-3].minor.yy404 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy404,yymsp[-2].minor.yy404);}
break;
case 148: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy153, &yymsp[-1].minor.yy0);
sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy153,yymsp[0].minor.yy404,0,0);
}
break;
case 153: /* where_opt_ret ::= RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy70); yymsp[-1].minor.yy404 = 0;}
break;
case 154: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy70); yymsp[-3].minor.yy404 = yymsp[-2].minor.yy404;}
break;
case 155: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy153, &yymsp[-4].minor.yy0);
sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy70,"set list");
yymsp[-5].minor.yy153 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy153, yymsp[-1].minor.yy153);
sqlite3Update(pParse,yymsp[-5].minor.yy153,yymsp[-2].minor.yy70,yymsp[0].minor.yy404,yymsp[-6].minor.yy376,0,0,0);
}
break;
case 156: /* setlist ::= setlist COMMA nm EQ expr */
{
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy70, yymsp[0].minor.yy404);
sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy70, &yymsp[-2].minor.yy0, 1);
}
break;
case 157: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
yymsp[-6].minor.yy70 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy70, yymsp[-3].minor.yy436, yymsp[0].minor.yy404);
}
break;
case 158: /* setlist ::= nm EQ expr */
{
yylhsminor.yy70 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy404);
sqlite3ExprListSetName(pParse, yylhsminor.yy70, &yymsp[-2].minor.yy0, 1);
}
yymsp[-2].minor.yy70 = yylhsminor.yy70;
break;
case 159: /* setlist ::= LP idlist RP EQ expr */
{
yymsp[-4].minor.yy70 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy436, yymsp[0].minor.yy404);
}
break;
case 160: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
sqlite3Insert(pParse, yymsp[-3].minor.yy153, yymsp[-1].minor.yy81, yymsp[-2].minor.yy436, yymsp[-5].minor.yy376, yymsp[0].minor.yy190);
}
break;
case 161: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
{
sqlite3Insert(pParse, yymsp[-4].minor.yy153, 0, yymsp[-3].minor.yy436, yymsp[-6].minor.yy376, 0);
}
break;
case 162: /* upsert ::= */
{ yymsp[1].minor.yy190 = 0; }
break;
case 163: /* upsert ::= RETURNING selcollist */
{ yymsp[-1].minor.yy190 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy70); }
break;
case 164: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
{ yymsp[-11].minor.yy190 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy70,yymsp[-6].minor.yy404,yymsp[-2].minor.yy70,yymsp[-1].minor.yy404,yymsp[0].minor.yy190);}
break;
case 165: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
{ yymsp[-8].minor.yy190 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy70,yymsp[-3].minor.yy404,0,0,yymsp[0].minor.yy190); }
break;
case 166: /* upsert ::= ON CONFLICT DO NOTHING returning */
{ yymsp[-4].minor.yy190 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
case 167: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
{ yymsp[-7].minor.yy190 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy70,yymsp[-1].minor.yy404,0);}
break;
case 168: /* returning ::= RETURNING selcollist */
{sqlite3AddReturning(pParse,yymsp[0].minor.yy70);}
break;
case 172: /* idlist_opt ::= LP idlist RP */
{yymsp[-2].minor.yy436 = yymsp[-1].minor.yy436;}
break;
case 173: /* idlist ::= idlist COMMA nm */
{yymsp[-2].minor.yy436 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy436,&yymsp[0].minor.yy0);}
break;
case 174: /* idlist ::= nm */
{yymsp[0].minor.yy436 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
case 175: /* expr ::= LP expr RP */
{yymsp[-2].minor.yy404 = yymsp[-1].minor.yy404;}
break;
case 176: /* expr ::= ID|INDEXED */
case 177: /* expr ::= JOIN_KW */ yytestcase(yyruleno==177);
{yymsp[0].minor.yy404=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 178: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
}
yylhsminor.yy404 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
yymsp[-2].minor.yy404 = yylhsminor.yy404;
break;
case 179: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
}
yylhsminor.yy404 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
yymsp[-4].minor.yy404 = yylhsminor.yy404;
break;
case 180: /* term ::= NULL|FLOAT|BLOB */
case 181: /* term ::= STRING */ yytestcase(yyruleno==181);
{yymsp[0].minor.yy404=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 182: /* term ::= INTEGER */
{
yylhsminor.yy404 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
yymsp[0].minor.yy404 = yylhsminor.yy404;
break;
case 183: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
yymsp[0].minor.yy404 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy404, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
** in the virtual machine. #N is the N-th register. */
Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
yymsp[0].minor.yy404 = 0;
}else{
yymsp[0].minor.yy404 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
if( yymsp[0].minor.yy404 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy404->iTable);
}
}
}
break;
case 184: /* expr ::= expr COLLATE ID|STRING */
{
yymsp[-2].minor.yy404 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy404, &yymsp[0].minor.yy0, 1);
}
break;
case 185: /* expr ::= CAST LP expr AS typetoken RP */
{
yymsp[-5].minor.yy404 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy404, yymsp[-3].minor.yy404, 0);
}
break;
case 186: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
yylhsminor.yy404 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy70, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy376);
}
yymsp[-4].minor.yy404 = yylhsminor.yy404;
break;
case 187: /* expr ::= ID|INDEXED LP STAR RP */
{
yylhsminor.yy404 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
yymsp[-3].minor.yy404 = yylhsminor.yy404;
break;
case 188: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
{
yylhsminor.yy404 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy70, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy376);
sqlite3WindowAttach(pParse, yylhsminor.yy404, yymsp[0].minor.yy49);
}
yymsp[-5].minor.yy404 = yylhsminor.yy404;
break;
case 189: /* expr ::= ID|INDEXED LP STAR RP filter_over */
{
yylhsminor.yy404 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
sqlite3WindowAttach(pParse, yylhsminor.yy404, yymsp[0].minor.yy49);
}
yymsp[-4].minor.yy404 = yylhsminor.yy404;
break;
case 190: /* term ::= CTIME_KW */
{
yylhsminor.yy404 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
yymsp[0].minor.yy404 = yylhsminor.yy404;
break;
case 191: /* expr ::= LP nexprlist COMMA expr RP */
{
ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy70, yymsp[-1].minor.yy404);
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
if( yymsp[-4].minor.yy404 ){
yymsp[-4].minor.yy404->x.pList = pList;
if( ALWAYS(pList->nExpr) ){
yymsp[-4].minor.yy404->flags |= pList->a[0].pExpr->flags & EP_Propagate;
}
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
}
break;
case 192: /* expr ::= expr AND expr */
{yymsp[-2].minor.yy404=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy404,yymsp[0].minor.yy404);}
break;
case 193: /* expr ::= expr OR expr */
case 194: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==194);
case 195: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==195);
case 196: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==196);
case 197: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==197);
case 198: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==198);
case 199: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==199);
{yymsp[-2].minor.yy404=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy404,yymsp[0].minor.yy404);}
break;
case 200: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
case 201: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy404);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy404);
yymsp[-2].minor.yy404 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
if( bNot ) yymsp[-2].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy404, 0);
if( yymsp[-2].minor.yy404 ) yymsp[-2].minor.yy404->flags |= EP_InfixFunc;
}
break;
case 202: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy404);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy404);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy404);
yymsp[-4].minor.yy404 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
if( bNot ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
if( yymsp[-4].minor.yy404 ) yymsp[-4].minor.yy404->flags |= EP_InfixFunc;
}
break;
case 203: /* expr ::= expr ISNULL|NOTNULL */
{yymsp[-1].minor.yy404 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy404,0);}
break;
case 204: /* expr ::= expr NOT NULL */
{yymsp[-2].minor.yy404 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy404,0);}
break;
case 205: /* expr ::= expr IS expr */
{
yymsp[-2].minor.yy404 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy404,yymsp[0].minor.yy404);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy404, yymsp[-2].minor.yy404, TK_ISNULL);
}
break;
case 206: /* expr ::= expr IS NOT expr */
{
yymsp[-3].minor.yy404 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy404,yymsp[0].minor.yy404);
binaryToUnaryIfNull(pParse, yymsp[0].minor.yy404, yymsp[-3].minor.yy404, TK_NOTNULL);
}
break;
case 207: /* expr ::= NOT expr */
case 208: /* expr ::= BITNOT expr */ yytestcase(yyruleno==208);
{yymsp[-1].minor.yy404 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy404, 0);/*A-overwrites-B*/}
break;
case 209: /* expr ::= PLUS|MINUS expr */
{
yymsp[-1].minor.yy404 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy404, 0);
/*A-overwrites-B*/
}
break;
case 210: /* between_op ::= BETWEEN */
case 213: /* in_op ::= IN */ yytestcase(yyruleno==213);
{yymsp[0].minor.yy376 = 0;}
break;
case 212: /* expr ::= expr between_op expr AND expr */
{
ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy404);
pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy404);
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy404, 0);
if( yymsp[-4].minor.yy404 ){
yymsp[-4].minor.yy404->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
}
break;
case 215: /* expr ::= expr in_op LP exprlist RP */
{
if( yymsp[-1].minor.yy70==0 ){
/* Expressions of the form
**
** expr1 IN ()
** expr1 NOT IN ()
**
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy404);
yymsp[-4].minor.yy404 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy376 ? "1" : "0");
}else if( yymsp[-1].minor.yy70->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy70->a[0].pExpr) ){
Expr *pRHS = yymsp[-1].minor.yy70->a[0].pExpr;
yymsp[-1].minor.yy70->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy404, pRHS);
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
}else{
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
if( yymsp[-4].minor.yy404 ){
yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy70;
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
}else{
sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy70);
}
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
}
}
break;
case 216: /* expr ::= LP select RP */
{
yymsp[-2].minor.yy404 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy404, yymsp[-1].minor.yy81);
}
break;
case 217: /* expr ::= expr in_op LP select RP */
{
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy404, yymsp[-1].minor.yy81);
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
}
break;
case 218: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
if( yymsp[0].minor.yy70 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy70);
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy404, 0);
sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy404, pSelect);
if( yymsp[-3].minor.yy376 ) yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy404, 0);
}
break;
case 219: /* expr ::= EXISTS LP select RP */
{
Expr *p;
p = yymsp[-3].minor.yy404 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy81);
}
break;
case 220: /* expr ::= CASE case_operand case_exprlist case_else END */
{
yymsp[-4].minor.yy404 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy404, 0);
if( yymsp[-4].minor.yy404 ){
yymsp[-4].minor.yy404->x.pList = yymsp[-1].minor.yy404 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy70,yymsp[-1].minor.yy404) : yymsp[-2].minor.yy70;
sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy404);
}else{
sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy70);
sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy404);
}
}
break;
case 221: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy70, yymsp[-2].minor.yy404);
yymsp[-4].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy70, yymsp[0].minor.yy404);
}
break;
case 222: /* case_exprlist ::= WHEN expr THEN expr */
{
yymsp[-3].minor.yy70 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy404);
yymsp[-3].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy70, yymsp[0].minor.yy404);
}
break;
case 225: /* case_operand ::= expr */
{yymsp[0].minor.yy404 = yymsp[0].minor.yy404; /*A-overwrites-X*/}
break;
case 228: /* nexprlist ::= nexprlist COMMA expr */
{yymsp[-2].minor.yy70 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy70,yymsp[0].minor.yy404);}
break;
case 229: /* nexprlist ::= expr */
{yymsp[0].minor.yy70 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy404); /*A-overwrites-Y*/}
break;
case 231: /* paren_exprlist ::= LP exprlist RP */
case 236: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==236);
{yymsp[-2].minor.yy70 = yymsp[-1].minor.yy70;}
break;
case 232: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy70, yymsp[-10].minor.yy376,
&yymsp[-11].minor.yy0, yymsp[0].minor.yy404, SQLITE_SO_ASC, yymsp[-8].minor.yy376, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
case 233: /* uniqueflag ::= UNIQUE */
case 275: /* raisetype ::= ABORT */ yytestcase(yyruleno==275);
{yymsp[0].minor.yy376 = OE_Abort;}
break;
case 234: /* uniqueflag ::= */
{yymsp[1].minor.yy376 = OE_None;}
break;
case 237: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
yymsp[-4].minor.yy70 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy70, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy376, yymsp[0].minor.yy376);
}
break;
case 238: /* eidlist ::= nm collate sortorder */
{
yymsp[-2].minor.yy70 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy376, yymsp[0].minor.yy376); /*A-overwrites-Y*/
}
break;
case 241: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy153, yymsp[-1].minor.yy376);}
break;
case 242: /* cmd ::= VACUUM vinto */
{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy404);}
break;
case 243: /* cmd ::= VACUUM nm vinto */
{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy404);}
break;
case 246: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
case 247: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
|
| ︙ | ︙ | |||
161505 161506 161507 161508 161509 161510 161511 |
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
case 253: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
| | | | | | | | | | | | | | | | 162498 162499 162500 162501 162502 162503 162504 162505 162506 162507 162508 162509 162510 162511 162512 162513 162514 162515 162516 162517 162518 162519 162520 162521 162522 162523 162524 162525 162526 162527 162528 162529 162530 162531 162532 162533 162534 162535 162536 162537 162538 162539 162540 162541 162542 162543 162544 162545 162546 162547 162548 162549 162550 162551 162552 162553 162554 162555 |
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
case 253: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy157, &all);
}
break;
case 254: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy376, yymsp[-4].minor.yy262.a, yymsp[-4].minor.yy262.b, yymsp[-2].minor.yy153, yymsp[0].minor.yy404, yymsp[-10].minor.yy376, yymsp[-8].minor.yy376);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
case 255: /* trigger_time ::= BEFORE|AFTER */
{ yymsp[0].minor.yy376 = yymsp[0].major; /*A-overwrites-X*/ }
break;
case 256: /* trigger_time ::= INSTEAD OF */
{ yymsp[-1].minor.yy376 = TK_INSTEAD;}
break;
case 257: /* trigger_time ::= */
{ yymsp[1].minor.yy376 = TK_BEFORE; }
break;
case 258: /* trigger_event ::= DELETE|INSERT */
case 259: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==259);
{yymsp[0].minor.yy262.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy262.b = 0;}
break;
case 260: /* trigger_event ::= UPDATE OF idlist */
{yymsp[-2].minor.yy262.a = TK_UPDATE; yymsp[-2].minor.yy262.b = yymsp[0].minor.yy436;}
break;
case 261: /* when_clause ::= */
case 280: /* key_opt ::= */ yytestcase(yyruleno==280);
{ yymsp[1].minor.yy404 = 0; }
break;
case 262: /* when_clause ::= WHEN expr */
case 281: /* key_opt ::= KEY expr */ yytestcase(yyruleno==281);
{ yymsp[-1].minor.yy404 = yymsp[0].minor.yy404; }
break;
case 263: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
assert( yymsp[-2].minor.yy157!=0 );
yymsp[-2].minor.yy157->pLast->pNext = yymsp[-1].minor.yy157;
yymsp[-2].minor.yy157->pLast = yymsp[-1].minor.yy157;
}
break;
case 264: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
assert( yymsp[-1].minor.yy157!=0 );
yymsp[-1].minor.yy157->pLast = yymsp[-1].minor.yy157;
}
break;
case 265: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
"qualified table names are not allowed on INSERT, UPDATE, and DELETE "
|
| ︙ | ︙ | |||
161574 161575 161576 161577 161578 161579 161580 |
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
case 268: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | > > > | | | | | | | | | | | | | | | 162567 162568 162569 162570 162571 162572 162573 162574 162575 162576 162577 162578 162579 162580 162581 162582 162583 162584 162585 162586 162587 162588 162589 162590 162591 162592 162593 162594 162595 162596 162597 162598 162599 162600 162601 162602 162603 162604 162605 162606 162607 162608 162609 162610 162611 162612 162613 162614 162615 162616 162617 162618 162619 162620 162621 162622 162623 162624 162625 162626 162627 162628 162629 162630 162631 162632 162633 162634 162635 162636 162637 162638 162639 162640 162641 162642 162643 162644 162645 162646 162647 162648 162649 162650 162651 162652 162653 162654 162655 162656 162657 162658 162659 162660 162661 162662 162663 162664 162665 162666 162667 162668 162669 162670 162671 162672 162673 162674 162675 162676 162677 162678 162679 162680 162681 162682 162683 162684 162685 162686 162687 162688 162689 162690 162691 162692 162693 162694 162695 162696 162697 162698 162699 162700 162701 162702 162703 162704 162705 162706 162707 162708 162709 162710 162711 162712 162713 162714 162715 162716 162717 162718 162719 162720 162721 162722 162723 162724 162725 162726 162727 162728 162729 162730 162731 162732 162733 162734 162735 162736 162737 162738 162739 162740 162741 162742 162743 162744 162745 162746 162747 162748 162749 162750 162751 162752 162753 162754 162755 162756 162757 162758 162759 162760 162761 162762 162763 162764 162765 162766 162767 162768 162769 162770 162771 162772 162773 162774 162775 162776 162777 162778 162779 162780 162781 162782 162783 162784 162785 162786 162787 162788 162789 162790 162791 162792 162793 162794 162795 162796 162797 162798 162799 162800 162801 162802 162803 162804 162805 162806 162807 162808 162809 162810 162811 162812 162813 162814 162815 162816 162817 162818 162819 162820 162821 162822 162823 162824 162825 162826 162827 162828 162829 162830 162831 162832 162833 162834 162835 162836 162837 162838 162839 162840 162841 162842 162843 162844 162845 162846 162847 162848 162849 162850 162851 162852 162853 162854 162855 162856 162857 162858 162859 162860 162861 162862 162863 162864 |
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
case 268: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
{yylhsminor.yy157 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy153, yymsp[-3].minor.yy70, yymsp[-1].minor.yy404, yymsp[-7].minor.yy376, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy504);}
yymsp[-8].minor.yy157 = yylhsminor.yy157;
break;
case 269: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
yylhsminor.yy157 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy436,yymsp[-2].minor.yy81,yymsp[-6].minor.yy376,yymsp[-1].minor.yy190,yymsp[-7].minor.yy504,yymsp[0].minor.yy504);/*yylhsminor.yy157-overwrites-yymsp[-6].minor.yy376*/
}
yymsp[-7].minor.yy157 = yylhsminor.yy157;
break;
case 270: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
{yylhsminor.yy157 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy404, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy504);}
yymsp[-5].minor.yy157 = yylhsminor.yy157;
break;
case 271: /* trigger_cmd ::= scanpt select scanpt */
{yylhsminor.yy157 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy81, yymsp[-2].minor.yy504, yymsp[0].minor.yy504); /*yylhsminor.yy157-overwrites-yymsp[-1].minor.yy81*/}
yymsp[-2].minor.yy157 = yylhsminor.yy157;
break;
case 272: /* expr ::= RAISE LP IGNORE RP */
{
yymsp[-3].minor.yy404 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
if( yymsp[-3].minor.yy404 ){
yymsp[-3].minor.yy404->affExpr = OE_Ignore;
}
}
break;
case 273: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
yymsp[-5].minor.yy404 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
if( yymsp[-5].minor.yy404 ) {
yymsp[-5].minor.yy404->affExpr = (char)yymsp[-3].minor.yy376;
}
}
break;
case 274: /* raisetype ::= ROLLBACK */
{yymsp[0].minor.yy376 = OE_Rollback;}
break;
case 276: /* raisetype ::= FAIL */
{yymsp[0].minor.yy376 = OE_Fail;}
break;
case 277: /* cmd ::= DROP TRIGGER ifexists fullname */
{
sqlite3DropTrigger(pParse,yymsp[0].minor.yy153,yymsp[-1].minor.yy376);
}
break;
case 278: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
sqlite3Attach(pParse, yymsp[-3].minor.yy404, yymsp[-1].minor.yy404, yymsp[0].minor.yy404);
}
break;
case 279: /* cmd ::= DETACH database_kw_opt expr */
{
sqlite3Detach(pParse, yymsp[0].minor.yy404);
}
break;
case 282: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
case 283: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
case 284: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
case 285: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
case 286: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy153,&yymsp[0].minor.yy0);
}
break;
case 287: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
case 288: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
{
sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy153, &yymsp[0].minor.yy0);
}
break;
case 289: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy153);
}
break;
case 290: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy153, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
case 291: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
case 292: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
case 293: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy376);
}
break;
case 294: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
case 295: /* vtabargtoken ::= ANY */
case 296: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==296);
case 297: /* lp ::= LP */ yytestcase(yyruleno==297);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
case 298: /* with ::= WITH wqlist */
case 299: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==299);
{ sqlite3WithPush(pParse, yymsp[0].minor.yy103, 1); }
break;
case 300: /* wqas ::= AS */
{yymsp[0].minor.yy552 = M10d_Any;}
break;
case 301: /* wqas ::= AS MATERIALIZED */
{yymsp[-1].minor.yy552 = M10d_Yes;}
break;
case 302: /* wqas ::= AS NOT MATERIALIZED */
{yymsp[-2].minor.yy552 = M10d_No;}
break;
case 303: /* wqitem ::= nm eidlist_opt wqas LP select RP */
{
yymsp[-5].minor.yy329 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy70, yymsp[-1].minor.yy81, yymsp[-3].minor.yy552); /*A-overwrites-X*/
}
break;
case 304: /* wqlist ::= wqitem */
{
yymsp[0].minor.yy103 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy329); /*A-overwrites-X*/
}
break;
case 305: /* wqlist ::= wqlist COMMA wqitem */
{
yymsp[-2].minor.yy103 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy103, yymsp[0].minor.yy329);
}
break;
case 306: /* windowdefn_list ::= windowdefn */
{ yylhsminor.yy49 = yymsp[0].minor.yy49; }
yymsp[0].minor.yy49 = yylhsminor.yy49;
break;
case 307: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
assert( yymsp[0].minor.yy49!=0 );
sqlite3WindowChain(pParse, yymsp[0].minor.yy49, yymsp[-2].minor.yy49);
yymsp[0].minor.yy49->pNextWin = yymsp[-2].minor.yy49;
yylhsminor.yy49 = yymsp[0].minor.yy49;
}
yymsp[-2].minor.yy49 = yylhsminor.yy49;
break;
case 308: /* windowdefn ::= nm AS LP window RP */
{
if( ALWAYS(yymsp[-1].minor.yy49) ){
yymsp[-1].minor.yy49->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
yylhsminor.yy49 = yymsp[-1].minor.yy49;
}
yymsp[-4].minor.yy49 = yylhsminor.yy49;
break;
case 309: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
yymsp[-4].minor.yy49 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy49, yymsp[-2].minor.yy70, yymsp[-1].minor.yy70, 0);
}
break;
case 310: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
yylhsminor.yy49 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy49, yymsp[-2].minor.yy70, yymsp[-1].minor.yy70, &yymsp[-5].minor.yy0);
}
yymsp[-5].minor.yy49 = yylhsminor.yy49;
break;
case 311: /* window ::= ORDER BY sortlist frame_opt */
{
yymsp[-3].minor.yy49 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy49, 0, yymsp[-1].minor.yy70, 0);
}
break;
case 312: /* window ::= nm ORDER BY sortlist frame_opt */
{
yylhsminor.yy49 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy49, 0, yymsp[-1].minor.yy70, &yymsp[-4].minor.yy0);
}
yymsp[-4].minor.yy49 = yylhsminor.yy49;
break;
case 313: /* window ::= frame_opt */
case 332: /* filter_over ::= over_clause */ yytestcase(yyruleno==332);
{
yylhsminor.yy49 = yymsp[0].minor.yy49;
}
yymsp[0].minor.yy49 = yylhsminor.yy49;
break;
case 314: /* window ::= nm frame_opt */
{
yylhsminor.yy49 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy49, 0, 0, &yymsp[-1].minor.yy0);
}
yymsp[-1].minor.yy49 = yylhsminor.yy49;
break;
case 315: /* frame_opt ::= */
{
yymsp[1].minor.yy49 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
case 316: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
yylhsminor.yy49 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy376, yymsp[-1].minor.yy117.eType, yymsp[-1].minor.yy117.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy552);
}
yymsp[-2].minor.yy49 = yylhsminor.yy49;
break;
case 317: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
yylhsminor.yy49 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy376, yymsp[-3].minor.yy117.eType, yymsp[-3].minor.yy117.pExpr, yymsp[-1].minor.yy117.eType, yymsp[-1].minor.yy117.pExpr, yymsp[0].minor.yy552);
}
yymsp[-5].minor.yy49 = yylhsminor.yy49;
break;
case 319: /* frame_bound_s ::= frame_bound */
case 321: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==321);
{yylhsminor.yy117 = yymsp[0].minor.yy117;}
yymsp[0].minor.yy117 = yylhsminor.yy117;
break;
case 320: /* frame_bound_s ::= UNBOUNDED PRECEDING */
case 322: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==322);
case 324: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==324);
{yylhsminor.yy117.eType = yymsp[-1].major; yylhsminor.yy117.pExpr = 0;}
yymsp[-1].minor.yy117 = yylhsminor.yy117;
break;
case 323: /* frame_bound ::= expr PRECEDING|FOLLOWING */
{yylhsminor.yy117.eType = yymsp[0].major; yylhsminor.yy117.pExpr = yymsp[-1].minor.yy404;}
yymsp[-1].minor.yy117 = yylhsminor.yy117;
break;
case 325: /* frame_exclude_opt ::= */
{yymsp[1].minor.yy552 = 0;}
break;
case 326: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
{yymsp[-1].minor.yy552 = yymsp[0].minor.yy552;}
break;
case 327: /* frame_exclude ::= NO OTHERS */
case 328: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==328);
{yymsp[-1].minor.yy552 = yymsp[-1].major; /*A-overwrites-X*/}
break;
case 329: /* frame_exclude ::= GROUP|TIES */
{yymsp[0].minor.yy552 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 330: /* window_clause ::= WINDOW windowdefn_list */
{ yymsp[-1].minor.yy49 = yymsp[0].minor.yy49; }
break;
case 331: /* filter_over ::= filter_clause over_clause */
{
if( yymsp[0].minor.yy49 ){
yymsp[0].minor.yy49->pFilter = yymsp[-1].minor.yy404;
}else{
sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy404);
}
yylhsminor.yy49 = yymsp[0].minor.yy49;
}
yymsp[-1].minor.yy49 = yylhsminor.yy49;
break;
case 333: /* filter_over ::= filter_clause */
{
yylhsminor.yy49 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( yylhsminor.yy49 ){
yylhsminor.yy49->eFrmType = TK_FILTER;
yylhsminor.yy49->pFilter = yymsp[0].minor.yy404;
}else{
sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy404);
}
}
yymsp[0].minor.yy49 = yylhsminor.yy49;
break;
case 334: /* over_clause ::= OVER LP window RP */
{
yymsp[-3].minor.yy49 = yymsp[-1].minor.yy49;
assert( yymsp[-3].minor.yy49!=0 );
}
break;
case 335: /* over_clause ::= OVER nm */
{
yymsp[-1].minor.yy49 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
if( yymsp[-1].minor.yy49 ){
yymsp[-1].minor.yy49->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
case 336: /* filter_clause ::= FILTER LP WHERE expr RP */
{ yymsp[-4].minor.yy404 = yymsp[-1].minor.yy404; }
break;
default:
/* (337) input ::= cmdlist */ yytestcase(yyruleno==337);
/* (338) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==338);
/* (339) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=339);
/* (340) ecmd ::= SEMI */ yytestcase(yyruleno==340);
/* (341) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==341);
|
| ︙ | ︙ | |||
162320 162321 162322 162323 162324 162325 162326 162327 162328 162329 162330 162331 162332 162333 162334 162335 162336 162337 162338 |
#define CC_COMMA 23 /* ',' */
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
#define CC_ID 27 /* unicode characters usable in IDs */
#define CC_ILLEGAL 28 /* Illegal character */
#define CC_NUL 29 /* 0x00 */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
| > | | | | | | | | | 163317 163318 163319 163320 163321 163322 163323 163324 163325 163326 163327 163328 163329 163330 163331 163332 163333 163334 163335 163336 163337 163338 163339 163340 163341 163342 163343 163344 163345 163346 163347 163348 163349 163350 163351 |
#define CC_COMMA 23 /* ',' */
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
#define CC_ID 27 /* unicode characters usable in IDs */
#define CC_ILLEGAL 28 /* Illegal character */
#define CC_NUL 29 /* 0x00 */
#define CC_BOM 30 /* First byte of UTF8 BOM: 0xEF 0xBB 0xBF */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
/* 8x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 9x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ax */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Cx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Dx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ex */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
/* Fx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28,
/* 1x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
| ︙ | ︙ | |||
163282 163283 163284 163285 163286 163287 163288 163289 163290 163291 163292 163293 163294 163295 |
#endif
/* If it is not a BLOB literal, then it must be an ID, since no
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
case CC_KYWD:
case CC_ID: {
i = 1;
break;
}
case CC_NUL: {
*tokenType = TK_ILLEGAL;
return 0;
}
| > > > > > > > > | 164280 164281 164282 164283 164284 164285 164286 164287 164288 164289 164290 164291 164292 164293 164294 164295 164296 164297 164298 164299 164300 164301 |
#endif
/* If it is not a BLOB literal, then it must be an ID, since no
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
case CC_KYWD:
case CC_ID: {
i = 1;
break;
}
case CC_BOM: {
if( z[1]==0xbb && z[2]==0xbf ){
*tokenType = TK_SPACE;
return 3;
}
i = 1;
break;
}
case CC_NUL: {
*tokenType = TK_ILLEGAL;
return 0;
}
|
| ︙ | ︙ | |||
164301 164302 164303 164304 164305 164306 164307 |
if( sqlite3GlobalConfig.isPCacheInit==0 ){
rc = sqlite3PcacheInitialize();
}
if( rc==SQLITE_OK ){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
| | | 165307 165308 165309 165310 165311 165312 165313 165314 165315 165316 165317 165318 165319 165320 165321 |
if( sqlite3GlobalConfig.isPCacheInit==0 ){
rc = sqlite3PcacheInitialize();
}
if( rc==SQLITE_OK ){
sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlite3OsInit();
}
#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlite3MemdbInit();
}
#endif
if( rc==SQLITE_OK ){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
|
| ︙ | ︙ | |||
164716 164717 164718 164719 164720 164721 164722 |
iVal = SQLITE_DEFAULT_SORTERREF_SIZE;
}
sqlite3GlobalConfig.szSorterRef = (u32)iVal;
break;
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
| | | | 165722 165723 165724 165725 165726 165727 165728 165729 165730 165731 165732 165733 165734 165735 165736 165737 165738 165739 165740 165741 |
iVal = SQLITE_DEFAULT_SORTERREF_SIZE;
}
sqlite3GlobalConfig.szSorterRef = (u32)iVal;
break;
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
break;
}
#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
break;
}
}
va_end(ap);
|
| ︙ | ︙ | |||
165270 165271 165272 165273 165274 165275 165276 | sqlite3_mutex_leave(db->mutex); return iTxn; } /* ** Two variations on the public interface for closing a database ** connection. The sqlite3_close() version returns SQLITE_BUSY and | | | 166276 166277 166278 166279 166280 166281 166282 166283 166284 166285 166286 166287 166288 166289 166290 |
sqlite3_mutex_leave(db->mutex);
return iTxn;
}
/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection open if there are unfinalized prepared
** statements or unfinished sqlite3_backups. The sqlite3_close_v2()
** version forces the connection to become a zombie if there are
** unclosed resources, and arranges for deallocation when the last
** prepare statement or sqlite3_backup closes.
*/
SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
|
| ︙ | ︙ | |||
165880 165881 165882 165883 165884 165885 165886 165887 165888 165889 165890 165891 165892 165893 |
sqlite3ErrorWithMsg(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
return SQLITE_BUSY;
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
assert(p || db->mallocFailed);
if( !p ){
return SQLITE_NOMEM_BKPT;
}
| > > > > | 166886 166887 166888 166889 166890 166891 166892 166893 166894 166895 166896 166897 166898 166899 166900 166901 166902 166903 |
sqlite3ErrorWithMsg(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
return SQLITE_BUSY;
}else{
sqlite3ExpirePreparedStatements(db, 0);
}
}else if( xSFunc==0 && xFinal==0 ){
/* Trying to delete a function that does not exist. This is a no-op.
** https://sqlite.org/forum/forumpost/726219164b */
return SQLITE_OK;
}
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
assert(p || db->mallocFailed);
if( !p ){
return SQLITE_NOMEM_BKPT;
}
|
| ︙ | ︙ | |||
168275 168276 168277 168278 168279 168280 168281 168282 168283 168284 168285 168286 168287 168288 |
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
return rc;
}
/*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 169285 169286 169287 169288 169289 169290 169291 169292 169293 169294 169295 169296 169297 169298 169299 169300 169301 169302 169303 169304 169305 169306 169307 169308 169309 169310 169311 169312 169313 169314 169315 169316 169317 169318 169319 169320 169321 169322 169323 169324 169325 169326 169327 169328 |
case 0: *ptr = sqlite3SelectTrace; break;
case 1: sqlite3SelectTrace = *ptr; break;
case 2: *ptr = sqlite3WhereTrace; break;
case 3: sqlite3WhereTrace = *ptr; break;
}
break;
}
#ifdef SQLITE_DEBUG
/* 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
** tuning parameter into *piValue.
**
** Tuning parameters are for use during transient development builds,
** to help find the best values for constants in the query planner.
** Access tuning parameters using the Tuning(ID) macro. Set the
** parameters in the CLI using ".testctrl tune ID VALUE".
**
** Transient use only. Tuning parameters should not be used in
** checked-in code.
*/
case SQLITE_TESTCTRL_TUNE: {
int id = va_arg(ap, int);
int *piValue = va_arg(ap, int*);
if( id>0 && id<=SQLITE_NTUNE ){
Tuning(id) = *piValue;
}else if( id<0 && id>=-SQLITE_NTUNE ){
*piValue = Tuning(-id);
}else{
rc = SQLITE_NOTFOUND;
}
break;
}
#endif
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
return rc;
}
/*
|
| ︙ | ︙ | |||
169717 169718 169719 169720 169721 169722 169723 | #define POS_END (0) /* Position-list terminator */ /* ** The assert_fts3_nc() macro is similar to the assert() macro, except that it ** is used for assert() conditions that are true only if it can be ** guranteed that the database is not corrupt. */ | | | 170757 170758 170759 170760 170761 170762 170763 170764 170765 170766 170767 170768 170769 170770 170771 | #define POS_END (0) /* Position-list terminator */ /* ** The assert_fts3_nc() macro is similar to the assert() macro, except that it ** is used for assert() conditions that are true only if it can be ** guranteed that the database is not corrupt. */ #ifdef SQLITE_DEBUG SQLITE_API extern int sqlite3_fts3_may_be_corrupt; # define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x)) #else # define assert_fts3_nc(x) assert(x) #endif /* |
| ︙ | ︙ | |||
170273 170274 170275 170276 170277 170278 170279 170280 170281 170282 170283 170284 170285 170286 170287 |
/*
** 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.
*/
SQLITE_API int sqlite3_fts3_may_be_corrupt = 1;
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
| > > | 171313 171314 171315 171316 171317 171318 171319 171320 171321 171322 171323 171324 171325 171326 171327 171328 171329 |
/*
** 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
SQLITE_API int sqlite3_fts3_may_be_corrupt = 1;
#endif
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
| ︙ | ︙ | |||
171844 171845 171846 171847 171848 171849 171850 |
){
int rc = SQLITE_OK; /* Return code */
const char *zCsr = zNode; /* Cursor to iterate through node */
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
| | | | | 172886 172887 172888 172889 172890 172891 172892 172893 172894 172895 172896 172897 172898 172899 172900 172901 172902 172903 172904 172905 172906 172907 172908 172909 172910 172911 172912 172913 172914 172915 172916 172917 |
){
int rc = SQLITE_OK; /* Return code */
const char *zCsr = zNode; /* Cursor to iterate through node */
const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
** interior node. Then load the blockid of the left-child of the b-tree
** node into variable iChild.
**
** Even if the data structure on disk is corrupted, this (reading two
** varints from the buffer) does not risk an overread. If zNode is a
** root node, then the buffer comes from a SELECT statement. SQLite does
** not make this guarantee explicitly, but in practice there are always
** either more than 20 bytes of allocated space following the nNode bytes of
** contents, or two zero bytes. Or, if the node is read from the %_segments
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
*/
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
while( zCsr<zEnd && (piFirst || piLast) ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
|
| ︙ | ︙ | |||
171914 171915 171916 171917 171918 171919 171920 |
** iChild.
**
** If the interior node term is larger than the specified term, then
** the tree headed by iChild may contain the specified term.
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
| | | | | | 172956 172957 172958 172959 172960 172961 172962 172963 172964 172965 172966 172967 172968 172969 172970 172971 172972 172973 172974 172975 172976 172977 172978 172979 172980 172981 172982 172983 |
** iChild.
**
** If the interior node term is larger than the specified term, then
** the tree headed by iChild may contain the specified term.
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
*piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
*piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
if( piFirst ) *piFirst = (i64)iChild;
if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlite3_free(zBuffer);
return rc;
}
|
| ︙ | ︙ | |||
173533 173534 173535 173536 173537 173538 173539 173540 173541 173542 173543 |
}
/*
** Implementation of xBegin() method.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(pVtab);
assert( p->pSegments==0 );
assert( p->nPendingData==0 );
assert( p->inTransaction!=1 );
| > > > > > | | < > > | | 174575 174576 174577 174578 174579 174580 174581 174582 174583 174584 174585 174586 174587 174588 174589 174590 174591 174592 174593 174594 174595 174596 174597 174598 174599 174600 174601 174602 |
}
/*
** Implementation of xBegin() method.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
int rc;
UNUSED_PARAMETER(pVtab);
assert( p->pSegments==0 );
assert( p->nPendingData==0 );
assert( p->inTransaction!=1 );
p->nLeafAdd = 0;
rc = fts3SetHasStat(p);
#ifdef SQLITE_DEBUG
if( rc==SQLITE_OK ){
p->inTransaction = 1;
p->mxSavepoint = -1;
}
#endif
return rc;
}
/*
** Implementation of xCommit() method. This is a no-op. The contents of
** the pending-terms hash-table have already been flushed into the database
** by fts3SyncMethod().
*/
|
| ︙ | ︙ | |||
175069 175070 175071 175072 175073 175074 175075 |
/* Allocate a MultiSegReader for each token in the expression. */
fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
/* Determine which, if any, tokens in the expression should be deferred. */
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
| < < > | 176117 176118 176119 176120 176121 176122 176123 176124 176125 176126 176127 176128 176129 176130 176131 176132 176133 176134 176135 176136 176137 176138 176139 |
/* Allocate a MultiSegReader for each token in the expression. */
fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
/* Determine which, if any, tokens in the expression should be deferred. */
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
if( !aTC ){
rc = SQLITE_NOMEM;
}else{
Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
int ii;
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
nToken = (int)(pTC-aTC);
nOr = (int)(ppOr-apOr);
|
| ︙ | ︙ | |||
176454 176455 176456 176457 176458 176459 176460 176461 176462 176463 176464 176465 176466 176467 |
}
/* In case this cursor is being reused, close and zero it. */
testcase(pCsr->filter.zTerm);
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->aStat);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
if( iEq>=0 || iGe>=0 ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
| > | 177501 177502 177503 177504 177505 177506 177507 177508 177509 177510 177511 177512 177513 177514 177515 |
}
/* In case this cursor is being reused, close and zero it. */
testcase(pCsr->filter.zTerm);
sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlite3_free((void *)pCsr->filter.zTerm);
sqlite3_free(pCsr->aStat);
sqlite3_free(pCsr->zStop);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
if( iEq>=0 || iGe>=0 ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
|
| ︙ | ︙ | |||
181975 181976 181977 181978 181979 181980 181981 |
}
}else{
rc = (pLhs->aNode==0) - (pRhs->aNode==0);
}
if( rc==0 ){
rc = pRhs->iIdx - pLhs->iIdx;
}
| | | 183023 183024 183025 183026 183027 183028 183029 183030 183031 183032 183033 183034 183035 183036 183037 |
}
}else{
rc = (pLhs->aNode==0) - (pRhs->aNode==0);
}
if( rc==0 ){
rc = pRhs->iIdx - pLhs->iIdx;
}
assert_fts3_nc( rc!=0 );
return rc;
}
/*
** A different comparison function for SegReader structures. In this
** version, it is assumed that each SegReader points to an entry in
** a doclist for identical terms. Comparison is made as follows:
|
| ︙ | ︙ | |||
185985 185986 185987 185988 185989 185990 185991 185992 185993 185994 185995 185996 185997 185998 | /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ /* ** Characters that may appear in the second argument to matchinfo(). */ #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ #define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ #define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ #define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ | > > > > | 187033 187034 187035 187036 187037 187038 187039 187040 187041 187042 187043 187044 187045 187046 187047 187048 187049 187050 | /* #include "fts3Int.h" */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) /* #include <string.h> */ /* #include <assert.h> */ #ifndef SQLITE_AMALGAMATION typedef sqlite3_int64 i64; #endif /* ** Characters that may appear in the second argument to matchinfo(). */ #define FTS3_MATCHINFO_NPHRASE 'p' /* 1 value */ #define FTS3_MATCHINFO_NCOL 'c' /* 1 value */ #define FTS3_MATCHINFO_NDOC 'n' /* 1 value */ #define FTS3_MATCHINFO_AVGLENGTH 'a' /* nCol values */ |
| ︙ | ︙ | |||
186035 186036 186037 186038 186039 186040 186041 |
SnippetPhrase *aPhrase; /* Array of size nPhrase */
int iCurrent; /* First token of current snippet */
};
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
| | | | 187087 187088 187089 187090 187091 187092 187093 187094 187095 187096 187097 187098 187099 187100 187101 187102 187103 |
SnippetPhrase *aPhrase; /* Array of size nPhrase */
int iCurrent; /* First token of current snippet */
};
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
i64 iHead; /* Next value in position list */
char *pHead; /* Position list data following iHead */
i64 iTail; /* Next value in trailing position list */
char *pTail; /* Position list data following iTail */
};
struct SnippetFragment {
int iCol; /* Column snippet is extracted from */
int iPos; /* Index of first token in snippet */
u64 covered; /* Mask of query phrases covered */
|
| ︙ | ︙ | |||
186202 186203 186204 186205 186206 186207 186208 | ** are encoded. ** ** When this function is called, *pp points to the start of an element of ** the list. *piPos contains the value of the previous entry in the list. ** After it returns, *piPos contains the value of the next element of the ** list and *pp is advanced to the following varint. */ | | | 187254 187255 187256 187257 187258 187259 187260 187261 187262 187263 187264 187265 187266 187267 187268 |
** are encoded.
**
** When this function is called, *pp points to the start of an element of
** the list. *piPos contains the value of the previous entry in the list.
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
static void fts3GetDeltaPosition(char **pp, i64 *piPos){
int iVal;
*pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
}
/*
** Helper function for fts3ExprIterate() (see below).
|
| ︙ | ︙ | |||
186311 186312 186313 186314 186315 186316 186317 | } /* ** Advance the position list iterator specified by the first two ** arguments so that it points to the first element with a value greater ** than or equal to parameter iNext. */ | | | | 187363 187364 187365 187366 187367 187368 187369 187370 187371 187372 187373 187374 187375 187376 187377 187378 187379 187380 |
}
/*
** Advance the position list iterator specified by the first two
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
i64 iIter = *piIter;
while( iIter<iNext ){
if( 0==(*pIter & 0xFE) ){
iIter = -1;
pIter = 0;
break;
}
|
| ︙ | ︙ | |||
186397 186398 186399 186400 186401 186402 186403 |
u64 mCover = 0; /* Mask of phrases covered by this snippet */
u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
| | | 187449 187450 187451 187452 187453 187454 187455 187456 187457 187458 187459 187460 187461 187462 187463 |
u64 mCover = 0; /* Mask of phrases covered by this snippet */
u64 mHighlight = 0; /* Mask of tokens to highlight in snippet */
for(i=0; i<pIter->nPhrase; i++){
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
i64 iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
u64 mPhrase = (u64)1 << (i%64);
u64 mPos = (u64)1 << (iCsr - iStart);
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
assert( i>=0 );
|
| ︙ | ︙ | |||
186443 186444 186445 186446 186447 186448 186449 |
char *pCsr;
int rc;
pPhrase->nToken = pExpr->pPhrase->nToken;
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( pCsr ){
| | | 187495 187496 187497 187498 187499 187500 187501 187502 187503 187504 187505 187506 187507 187508 187509 |
char *pCsr;
int rc;
pPhrase->nToken = pExpr->pPhrase->nToken;
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( pCsr ){
i64 iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
if( iFirst<0 ){
rc = FTS_CORRUPT_VTAB;
}else{
pPhrase->pHead = pCsr;
pPhrase->pTail = pCsr;
|
| ︙ | ︙ | |||
187507 187508 187509 187510 187511 187512 187513 |
typedef struct TermOffset TermOffset;
typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
| | | | | 188559 188560 188561 188562 188563 188564 188565 188566 188567 188568 188569 188570 188571 188572 188573 188574 188575 188576 188577 188578 188579 188580 188581 188582 188583 188584 188585 188586 188587 188588 188589 188590 188591 188592 188593 |
typedef struct TermOffset TermOffset;
typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
i64 iPos; /* Position just read from pList */
i64 iOff; /* Offset of this term from read positions */
};
struct TermOffsetCtx {
Fts3Cursor *pCsr;
int iCol; /* Column of table to populate aTerm for */
int iTerm;
sqlite3_int64 iDocid;
TermOffset *aTerm;
};
/*
** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
*/
static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
TermOffsetCtx *p = (TermOffsetCtx *)ctx;
int nTerm; /* Number of tokens in phrase */
int iTerm; /* For looping through nTerm phrase terms */
char *pList; /* Pointer to position list for phrase */
i64 iPos = 0; /* First position in position-list */
int rc;
UNUSED_PARAMETER(iPhrase);
rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
nTerm = pExpr->pPhrase->nToken;
if( pList ){
fts3GetDeltaPosition(&pList, &iPos);
|
| ︙ | ︙ | |||
188804 188805 188806 188807 188808 188809 188810 |
/* Append the N-byte string in zIn to the end of the JsonString string
** under construction. Enclose the string in "..." and escape
** any double-quotes or backslash characters contained within the
** string.
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
| | | 189856 189857 189858 189859 189860 189861 189862 189863 189864 189865 189866 189867 189868 189869 189870 |
/* Append the N-byte string in zIn to the end of the JsonString string
** under construction. Enclose the string in "..." and escape
** any double-quotes or backslash characters contained within the
** string.
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
p->zBuf[p->nUsed++] = '"';
for(i=0; i<N; i++){
unsigned char c = ((unsigned const char*)zIn)[i];
if( c=='"' || c=='\\' ){
json_simple_escape:
if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
p->zBuf[p->nUsed++] = '\\';
|
| ︙ | ︙ | |||
190403 190404 190405 190406 190407 190408 190409 |
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '[');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
| < > | 191455 191456 191457 191458 191459 191460 191461 191462 191463 191464 191465 191466 191467 191468 191469 191470 |
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '[');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
jsonAppendValue(pStr, argv[0]);
}
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
JsonString *pStr;
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
|
| ︙ | ︙ | |||
190464 190465 190466 190467 190468 190469 190470 | pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will ** always have been called to initalize it */ if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; | | < < < < > | | > > > > | 191516 191517 191518 191519 191520 191521 191522 191523 191524 191525 191526 191527 191528 191529 191530 191531 191532 191533 191534 191535 191536 191537 191538 191539 191540 191541 191542 191543 191544 191545 191546 |
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
** always have been called to initalize it */
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
inStr = !inStr;
}else if( c=='\\' ){
i++;
}else if( !inStr ){
if( c=='{' || c=='[' ) nNest++;
if( c=='}' || c==']' ) nNest--;
}
}
if( i<pStr->nUsed ){
pStr->nUsed -= i;
memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
z[pStr->nUsed] = 0;
}else{
pStr->nUsed = 1;
}
}
#else
# define jsonGroupInverse 0
#endif
/*
|
| ︙ | ︙ | |||
190507 190508 190509 190510 190511 190512 190513 |
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
| < > | 191560 191561 191562 191563 191564 191565 191566 191567 191568 191569 191570 191571 191572 191573 191574 191575 |
pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
jsonInit(pStr, ctx);
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
}
pStr->pCtx = ctx;
z = (const char*)sqlite3_value_text(argv[0]);
n = (u32)sqlite3_value_bytes(argv[0]);
jsonAppendString(pStr, z, n);
jsonAppendChar(pStr, ':');
jsonAppendValue(pStr, argv[1]);
}
}
|
| ︙ | ︙ | |||
195029 195030 195031 195032 195033 195034 195035 195036 195037 195038 195039 |
** node always has nodeno=1, so the example above is the primary use for this
** routine. This routine is intended for testing and analysis only.
*/
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
){
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
| > > | > > > | 196082 196083 196084 196085 196086 196087 196088 196089 196090 196091 196092 196093 196094 196095 196096 196097 196098 196099 196100 196101 196102 196103 196104 196105 |
** node always has nodeno=1, so the example above is the primary use for this
** routine. This routine is intended for testing and analysis only.
*/
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
){
sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
if( zBlob ){
sqlite3_result_int(ctx, readInt16(zBlob));
}else{
sqlite3_result_error_nomem(ctx);
}
}
}
/*
** Context object passed between the various routines that make up the
** implementation of integrity-check function rtreecheck().
*/
|
| ︙ | ︙ | |||
195819 195820 195821 195822 195823 195824 195825 195826 195827 195828 195829 195830 195831 195832 |
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;
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) );
if( p==0 ){
if( pRc ) *pRc = SQLITE_NOMEM;
| > > > > | 196877 196878 196879 196880 196881 196882 196883 196884 196885 196886 196887 196888 196889 196890 196891 196892 196893 196894 |
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 ){
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) );
if( p==0 ){
if( pRc ) *pRc = SQLITE_NOMEM;
|
| ︙ | ︙ | |||
196192 196193 196194 196195 196196 196197 196198 |
}else{
sqlite3_free(p);
aCoord[0].f = mnX;
aCoord[1].f = mxX;
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
| | | 197254 197255 197256 197257 197258 197259 197260 197261 197262 197263 197264 197265 197266 197267 197268 |
}else{
sqlite3_free(p);
aCoord[0].f = mnX;
aCoord[1].f = mxX;
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
}else if( aCoord ){
memset(aCoord, 0, sizeof(RtreeCoord)*4);
}
return pOut;
}
/*
** Implementation of the geopoly_bbox(X) SQL function.
|
| ︙ | ︙ | |||
200552 200553 200554 200555 200556 200557 200558 |
zSelect, pIter->zTbl, zOrder
)
);
if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){
zSep = "";
for(iCol=0; iCol<pIter->nCol; iCol++){
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
| > > | | 201614 201615 201616 201617 201618 201619 201620 201621 201622 201623 201624 201625 201626 201627 201628 201629 201630 |
zSelect, pIter->zTbl, zOrder
)
);
if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){
zSep = "";
for(iCol=0; iCol<pIter->nCol; iCol++){
const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
if( zQuoted==0 ){
p->rc = SQLITE_NOMEM;
}else if( zQuoted[0]=='N' ){
bFailed = 1;
break;
}
zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
zSep = ", ";
}
|
| ︙ | ︙ | |||
203924 203925 203926 203927 203928 203929 203930 |
** or xOpen() to operate on the *-wal file. */
pFd->zWal = sqlite3_filename_wal(zName);
}
else if( flags & SQLITE_OPEN_WAL ){
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
| | < < < < | < | | | < < < | < < < < < < | 204988 204989 204990 204991 204992 204993 204994 204995 204996 204997 204998 204999 205000 205001 205002 205003 205004 205005 205006 205007 205008 205009 |
** or xOpen() to operate on the *-wal file. */
pFd->zWal = sqlite3_filename_wal(zName);
}
else if( flags & SQLITE_OPEN_WAL ){
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
/* This call is to open a *-wal file. Intead, open the *-oal. */
size_t nOpen;
if( rbuIsVacuum(pDb->pRbu) ){
zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
zOpen = sqlite3_filename_wal(zOpen);
}
nOpen = strlen(zOpen);
((char*)zOpen)[nOpen-3] = 'o';
pFd->pRbu = pDb->pRbu;
}
pDb->pWalFd = pFd;
}
}
}else{
pFd->pRbu = pRbuVfs->pRbu;
|
| ︙ | ︙ | |||
205558 205559 205560 205561 205562 205563 205564 205565 205566 205567 205568 205569 205570 205571 205572 205573 205574 205575 205576 205577 205578 |
/*
** Session handle structure.
*/
struct sqlite3_session {
sqlite3 *db; /* Database handle session is attached to */
char *zDb; /* Name of database session is attached to */
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
i64 nMalloc; /* Number of bytes of data allocated */
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
SessionHook hook; /* APIs to grab new and old data with */
};
/*
| > > | 206608 206609 206610 206611 206612 206613 206614 206615 206616 206617 206618 206619 206620 206621 206622 206623 206624 206625 206626 206627 206628 206629 206630 |
/*
** Session handle structure.
*/
struct sqlite3_session {
sqlite3 *db; /* Database handle session is attached to */
char *zDb; /* Name of database session is attached to */
int bEnableSize; /* True if changeset_size() enabled */
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
i64 nMalloc; /* Number of bytes of data allocated */
i64 nMaxChangesetSize;
sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
SessionHook hook; /* APIs to grab new and old data with */
};
/*
|
| ︙ | ︙ | |||
205807 205808 205809 205810 205811 205812 205813 |
*/
/*
** For each row modified during a session, there exists a single instance of
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
| | | > | 206859 206860 206861 206862 206863 206864 206865 206866 206867 206868 206869 206870 206871 206872 206873 206874 206875 |
*/
/*
** For each row modified during a session, there exists a single instance of
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
u8 op; /* One of UPDATE, DELETE, INSERT */
u8 bIndirect; /* True if this change is "indirect" */
int nMaxSize; /* Max size of eventual changeset record */
int nRecord; /* Number of bytes in buffer aRecord[] */
u8 *aRecord; /* Buffer containing old.* record */
SessionChange *pNext; /* For hash-table collisions */
};
/*
** Write a varint with value iVal into the buffer at aBuf. Return the
|
| ︙ | ︙ | |||
206637 206638 206639 206640 206641 206642 206643 206644 206645 206646 206647 206648 206649 206650 |
pTab->abPK = abPK;
break;
}
}
if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
pTab->bStat1 = 1;
}
}
}
return (pSession->rc || pTab->abPK==0);
}
/*
** Versions of the four methods in object SessionHook for use with the
| > > > > > > | 207690 207691 207692 207693 207694 207695 207696 207697 207698 207699 207700 207701 207702 207703 207704 207705 207706 207707 207708 207709 |
pTab->abPK = abPK;
break;
}
}
if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
pTab->bStat1 = 1;
}
if( pSession->bEnableSize ){
pSession->nMaxChangesetSize += (
1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1
);
}
}
}
return (pSession->rc || pTab->abPK==0);
}
/*
** Versions of the four methods in object SessionHook for use with the
|
| ︙ | ︙ | |||
206682 206683 206684 206685 206686 206687 206688 206689 206690 206691 206692 206693 206694 206695 |
return p->hook.xCount(p->hook.pCtx);
}
static int sessionStat1Depth(void *pCtx){
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
return p->hook.xDepth(p->hook.pCtx);
}
/*
** This function is only called from with a pre-update-hook reporting a
** change on table pTab (attached to session pSession). The type of change
** (UPDATE, INSERT, DELETE) is specified by the first argument.
**
** Unless one is already present or an error occurs, an entry is added
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 207741 207742 207743 207744 207745 207746 207747 207748 207749 207750 207751 207752 207753 207754 207755 207756 207757 207758 207759 207760 207761 207762 207763 207764 207765 207766 207767 207768 207769 207770 207771 207772 207773 207774 207775 207776 207777 207778 207779 207780 207781 207782 207783 207784 207785 207786 207787 207788 207789 207790 207791 207792 207793 207794 207795 207796 207797 207798 207799 207800 207801 207802 207803 207804 207805 207806 207807 207808 207809 207810 207811 207812 207813 207814 207815 207816 207817 207818 207819 207820 207821 207822 207823 207824 207825 207826 207827 207828 207829 207830 207831 207832 207833 207834 207835 207836 207837 207838 207839 207840 207841 207842 207843 207844 207845 207846 207847 207848 207849 207850 207851 |
return p->hook.xCount(p->hook.pCtx);
}
static int sessionStat1Depth(void *pCtx){
SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
return p->hook.xDepth(p->hook.pCtx);
}
static int sessionUpdateMaxSize(
int op,
sqlite3_session *pSession, /* Session object pTab is attached to */
SessionTable *pTab, /* Table that change applies to */
SessionChange *pC /* Update pC->nMaxSize */
){
i64 nNew = 2;
if( pC->op==SQLITE_INSERT ){
if( op!=SQLITE_DELETE ){
int ii;
for(ii=0; ii<pTab->nCol; ii++){
sqlite3_value *p = 0;
pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
sessionSerializeValue(0, p, &nNew);
}
}
}else if( op==SQLITE_DELETE ){
nNew += pC->nRecord;
if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){
nNew += pC->nRecord;
}
}else{
int ii;
u8 *pCsr = pC->aRecord;
for(ii=0; ii<pTab->nCol; ii++){
int bChanged = 1;
int nOld = 0;
int eType;
sqlite3_value *p = 0;
pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
if( p==0 ){
return SQLITE_NOMEM;
}
eType = *pCsr++;
switch( eType ){
case SQLITE_NULL:
bChanged = sqlite3_value_type(p)!=SQLITE_NULL;
break;
case SQLITE_FLOAT:
case SQLITE_INTEGER: {
if( eType==sqlite3_value_type(p) ){
sqlite3_int64 iVal = sessionGetI64(pCsr);
if( eType==SQLITE_INTEGER ){
bChanged = (iVal!=sqlite3_value_int64(p));
}else{
double dVal;
memcpy(&dVal, &iVal, 8);
bChanged = (dVal!=sqlite3_value_double(p));
}
}
nOld = 8;
pCsr += 8;
break;
}
default: {
int nByte;
nOld = sessionVarintGet(pCsr, &nByte);
pCsr += nOld;
nOld += nByte;
assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
if( eType==sqlite3_value_type(p)
&& nByte==sqlite3_value_bytes(p)
&& (nByte==0 || 0==memcmp(pCsr, sqlite3_value_blob(p), nByte))
){
bChanged = 0;
}
pCsr += nByte;
break;
}
}
if( bChanged && pTab->abPK[ii] ){
nNew = pC->nRecord + 2;
break;
}
if( bChanged ){
nNew += 1 + nOld;
sessionSerializeValue(0, p, &nNew);
}else if( pTab->abPK[ii] ){
nNew += 2 + nOld;
}else{
nNew += 2;
}
}
}
if( nNew>pC->nMaxSize ){
int nIncr = nNew - pC->nMaxSize;
pC->nMaxSize = nNew;
pSession->nMaxChangesetSize += nIncr;
}
return SQLITE_OK;
}
/*
** This function is only called from with a pre-update-hook reporting a
** change on table pTab (attached to session pSession). The type of change
** (UPDATE, INSERT, DELETE) is specified by the first argument.
**
** Unless one is already present or an error occurs, an entry is added
|
| ︙ | ︙ | |||
206755 206756 206757 206758 206759 206760 206761 |
if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
}
if( pC==0 ){
/* Create a new change object containing all the old values (if
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
| < | 207911 207912 207913 207914 207915 207916 207917 207918 207919 207920 207921 207922 207923 207924 |
if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
}
if( pC==0 ){
/* Create a new change object containing all the old values (if
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
assert( rc==SQLITE_OK );
pTab->nEntry++;
/* Figure out how large an allocation is required */
|
| ︙ | ︙ | |||
206781 206782 206783 206784 206785 206786 206787 |
/* This may fail if SQLite value p contains a utf-16 string that must
** be converted to utf-8 and an OOM error occurs while doing so. */
rc = sessionSerializeValue(0, p, &nByte);
if( rc!=SQLITE_OK ) goto error_out;
}
/* Allocate the change object */
| | | | | | | | | | | | > > > > > > | 207936 207937 207938 207939 207940 207941 207942 207943 207944 207945 207946 207947 207948 207949 207950 207951 207952 207953 207954 207955 207956 207957 207958 207959 207960 207961 207962 207963 207964 207965 207966 207967 207968 207969 207970 207971 207972 207973 207974 207975 207976 207977 207978 207979 207980 207981 207982 207983 207984 207985 207986 207987 207988 207989 207990 207991 207992 207993 207994 207995 207996 207997 207998 |
/* This may fail if SQLite value p contains a utf-16 string that must
** be converted to utf-8 and an OOM error occurs while doing so. */
rc = sessionSerializeValue(0, p, &nByte);
if( rc!=SQLITE_OK ) goto error_out;
}
/* Allocate the change object */
pC = (SessionChange *)sessionMalloc64(pSession, nByte);
if( !pC ){
rc = SQLITE_NOMEM;
goto error_out;
}else{
memset(pC, 0, sizeof(SessionChange));
pC->aRecord = (u8 *)&pC[1];
}
/* Populate the change object. None of the preupdate_old(),
** preupdate_new() or SerializeValue() calls below may fail as all
** required values and encodings have already been cached in memory.
** It is not possible for an OOM to occur in this block. */
nByte = 0;
for(i=0; i<pTab->nCol; i++){
sqlite3_value *p = 0;
if( op!=SQLITE_INSERT ){
pSession->hook.xOld(pSession->hook.pCtx, i, &p);
}else if( pTab->abPK[i] ){
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
}
sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
}
/* Add the change to the hash-table */
if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
pC->bIndirect = 1;
}
pC->nRecord = nByte;
pC->op = op;
pC->pNext = pTab->apChange[iHash];
pTab->apChange[iHash] = pC;
}else if( pC->bIndirect ){
/* If the existing change is considered "indirect", but this current
** change is "direct", mark the change object as direct. */
if( pSession->hook.xDepth(pSession->hook.pCtx)==0
&& pSession->bIndirect==0
){
pC->bIndirect = 0;
}
}
assert( rc==SQLITE_OK );
if( pSession->bEnableSize ){
rc = sessionUpdateMaxSize(op, pSession, pTab, pC);
}
}
/* If an error has occurred, mark the session object as failed. */
error_out:
if( pTab->bStat1 ){
pSession->hook = stat1.hook;
}
if( rc!=SQLITE_OK ){
|
| ︙ | ︙ | |||
207379 207380 207381 207382 207383 207384 207385 | /* ** Ensure that there is room in the buffer to append nByte bytes of data. ** If not, use sqlite3_realloc() to grow the buffer so that there is. ** ** If successful, return zero. Otherwise, if an OOM condition is encountered, ** set *pRc to SQLITE_NOMEM and return non-zero. */ | | > > | > > | > > > > > > > > > > > > | 208540 208541 208542 208543 208544 208545 208546 208547 208548 208549 208550 208551 208552 208553 208554 208555 208556 208557 208558 208559 208560 208561 208562 208563 208564 208565 208566 208567 208568 208569 208570 208571 208572 208573 208574 208575 208576 |
/*
** Ensure that there is room in the buffer to append nByte bytes of data.
** If not, use sqlite3_realloc() to grow the buffer so that there is.
**
** If successful, return zero. Otherwise, if an OOM condition is encountered,
** set *pRc to SQLITE_NOMEM and return non-zero.
*/
static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){
#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1)
i64 nReq = p->nBuf + nByte;
if( *pRc==SQLITE_OK && nReq>p->nAlloc ){
u8 *aNew;
i64 nNew = p->nAlloc ? p->nAlloc : 128;
do {
nNew = nNew*2;
}while( nNew<nReq );
/* The value of SESSION_MAX_BUFFER_SZ is copied from the implementation
** of sqlite3_realloc64(). Allocations greater than this size in bytes
** always fail. It is used here to ensure that this routine can always
** allocate up to this limit - instead of up to the largest power of
** two smaller than the limit. */
if( nNew>SESSION_MAX_BUFFER_SZ ){
nNew = SESSION_MAX_BUFFER_SZ;
if( nNew<nReq ){
*pRc = SQLITE_NOMEM;
return 1;
}
}
aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
if( 0==aNew ){
*pRc = SQLITE_NOMEM;
}else{
p->aBuf = aNew;
p->nAlloc = nNew;
|
| ︙ | ︙ | |||
208036 208037 208038 208039 208040 208041 208042 |
** 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 */
){
| | > > > > | 209213 209214 209215 209216 209217 209218 209219 209220 209221 209222 209223 209224 209225 209226 209227 209228 209229 209230 209231 |
** 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 = 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,
|
| ︙ | ︙ | |||
208127 208128 208129 208130 208131 208132 208133 208134 208135 208136 208137 208138 208139 208140 |
/*
** Return the amount of heap memory in use.
*/
SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
return pSession->nMalloc;
}
/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
int (*xInput)(void *pIn, void *pData, int *pnData),
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 209308 209309 209310 209311 209312 209313 209314 209315 209316 209317 209318 209319 209320 209321 209322 209323 209324 209325 209326 209327 209328 209329 209330 209331 209332 209333 209334 209335 209336 209337 209338 209339 209340 209341 209342 209343 209344 209345 209346 209347 209348 209349 209350 209351 209352 209353 209354 |
/*
** Return the amount of heap memory in use.
*/
SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
return pSession->nMalloc;
}
/*
** Configure the session object passed as the first argument.
*/
SQLITE_API int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){
int rc = SQLITE_OK;
switch( op ){
case SQLITE_SESSION_OBJCONFIG_SIZE: {
int iArg = *(int*)pArg;
if( iArg>=0 ){
if( pSession->pTable ){
rc = SQLITE_MISUSE;
}else{
pSession->bEnableSize = (iArg!=0);
}
}
*(int*)pArg = pSession->bEnableSize;
break;
}
default:
rc = SQLITE_MISUSE;
}
return rc;
}
/*
** Return the maximum size of sqlite3session_changeset() output.
*/
SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession){
return pSession->nMaxChangesetSize;
}
/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
int (*xInput)(void *pIn, void *pData, int *pnData),
|
| ︙ | ︙ | |||
215711 215712 215713 215714 215715 215716 215717 | if( pRet==0 ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(Fts5Config)); pRet->db = db; pRet->iCookie = -1; nByte = nArg * (sizeof(char*) + sizeof(u8)); pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte); | | | 216925 216926 216927 216928 216929 216930 216931 216932 216933 216934 216935 216936 216937 216938 216939 | if( pRet==0 ) return SQLITE_NOMEM; memset(pRet, 0, sizeof(Fts5Config)); pRet->db = db; pRet->iCookie = -1; nByte = nArg * (sizeof(char*) + sizeof(u8)); pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte); pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0; pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1); pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1); pRet->bColumnsize = 1; pRet->eDetail = FTS5_DETAIL_FULL; #ifdef SQLITE_DEBUG pRet->bPrefixIndex = 1; #endif |
| ︙ | ︙ | |||
218547 218548 218549 218550 218551 218552 218553 218554 218555 218556 218557 218558 218559 218560 |
pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
}
}
return pRet;
}
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
/* Determine the maximum amount of space required. */
for(p=pTerm; p; p=p->pSynonym){
| > | 219761 219762 219763 219764 219765 219766 219767 219768 219769 219770 219771 219772 219773 219774 219775 |
pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
}
}
return pRet;
}
#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
/* Determine the maximum amount of space required. */
for(p=pTerm; p; p=p->pSynonym){
|
| ︙ | ︙ | |||
218913 218914 218915 218916 218917 218918 218919 218920 218921 218922 218923 218924 218925 218926 218927 218928 218929 218930 218931 218932 218933 218934 218935 218936 218937 218938 218939 218940 218941 218942 218943 218944 218945 218946 218947 218948 218949 |
int iCode;
int bRemoveDiacritics = 0;
iCode = sqlite3_value_int(apVal[0]);
if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]);
sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
}
}
/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
static int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
struct Fts5ExprFunc {
const char *z;
void (*x)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "fts5_expr", fts5ExprFunctionHr },
{ "fts5_expr_tcl", fts5ExprFunctionTcl },
{ "fts5_isalnum", fts5ExprIsAlnum },
{ "fts5_fold", fts5ExprFold },
};
int i;
int rc = SQLITE_OK;
void *pCtx = (void*)pGlobal;
for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
/* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
** sqlite3Fts5ParserFallback() are unused */
#ifndef NDEBUG
(void)sqlite3Fts5ParserTrace;
#endif
(void)sqlite3Fts5ParserFallback;
| > > > > > > | 220128 220129 220130 220131 220132 220133 220134 220135 220136 220137 220138 220139 220140 220141 220142 220143 220144 220145 220146 220147 220148 220149 220150 220151 220152 220153 220154 220155 220156 220157 220158 220159 220160 220161 220162 220163 220164 220165 220166 220167 220168 220169 220170 |
int iCode;
int bRemoveDiacritics = 0;
iCode = sqlite3_value_int(apVal[0]);
if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]);
sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
}
}
#endif /* ifdef SQLITE_TEST */
/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
static int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
#ifdef SQLITE_TEST
struct Fts5ExprFunc {
const char *z;
void (*x)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "fts5_expr", fts5ExprFunctionHr },
{ "fts5_expr_tcl", fts5ExprFunctionTcl },
{ "fts5_isalnum", fts5ExprIsAlnum },
{ "fts5_fold", fts5ExprFold },
};
int i;
int rc = SQLITE_OK;
void *pCtx = (void*)pGlobal;
for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
#else
int rc = SQLITE_OK;
UNUSED_PARAM2(pGlobal,db);
#endif
/* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
** sqlite3Fts5ParserFallback() are unused */
#ifndef NDEBUG
(void)sqlite3Fts5ParserTrace;
#endif
(void)sqlite3Fts5ParserFallback;
|
| ︙ | ︙ | |||
220182 220183 220184 220185 220186 220187 220188 |
*/
struct Fts5SegIter {
Fts5StructureSegment *pSeg; /* Segment to iterate through */
int flags; /* Mask of configuration flags */
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
| | | 221403 221404 221405 221406 221407 221408 221409 221410 221411 221412 221413 221414 221415 221416 221417 |
*/
struct Fts5SegIter {
Fts5StructureSegment *pSeg; /* Segment to iterate through */
int flags; /* Mask of configuration flags */
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
i64 iLeafOffset; /* Byte offset within current leaf */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
/* The page and offset from which the current term was read. The offset
** is the offset of the first rowid in the current doclist. */
int iTermLeafPgno;
|
| ︙ | ︙ | |||
221362 221363 221364 221365 221366 221367 221368 |
}
pIter->iLeafOffset = iOff;
}
}
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
| | | 222583 222584 222585 222586 222587 222588 222589 222590 222591 222592 222593 222594 222595 222596 222597 |
}
pIter->iLeafOffset = iOff;
}
}
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
i64 iOff = pIter->iLeafOffset;
ASSERT_SZLEAF_OK(pIter->pLeaf);
if( iOff>=pIter->pLeaf->szLeaf ){
fts5SegIterNextPage(p, pIter);
if( pIter->pLeaf==0 ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
return;
|
| ︙ | ︙ | |||
221395 221396 221397 221398 221399 221400 221401 |
**
** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
** the first position list. The position list belonging to document
** (Fts5SegIter.iRowid).
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
| | | 222616 222617 222618 222619 222620 222621 222622 222623 222624 222625 222626 222627 222628 222629 222630 |
**
** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
** the first position list. The position list belonging to document
** (Fts5SegIter.iRowid).
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
i64 iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
p->rc = FTS5_CORRUPT;
return;
}
|
| ︙ | ︙ | |||
221823 221824 221825 221826 221827 221828 221829 |
if( pbNewTerm ) *pbNewTerm = 1;
}
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
** code is inlined. */
int nSz;
| < | 223044 223045 223046 223047 223048 223049 223050 223051 223052 223053 223054 223055 223056 223057 |
if( pbNewTerm ) *pbNewTerm = 1;
}
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
** code is inlined. */
int nSz;
assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
assert_nc( pIter->nPos>=0 );
}
}
|
| ︙ | ︙ | |||
224292 224293 224294 224295 224296 224297 224298 |
assert( writer.bFirstRowidInPage==0 );
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
/* The entire doclist will fit on the current leaf. */
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
}else{
i64 iRowid = 0;
| | | | 225512 225513 225514 225515 225516 225517 225518 225519 225520 225521 225522 225523 225524 225525 225526 225527 225528 225529 225530 225531 225532 225533 |
assert( writer.bFirstRowidInPage==0 );
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
/* The entire doclist will fit on the current leaf. */
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
}else{
i64 iRowid = 0;
u64 iDelta = 0;
int iOff = 0;
/* The entire doclist will not fit on this leaf. The following
** loop iterates through the poslists that make up the current
** doclist. */
while( p->rc==SQLITE_OK && iOff<nDoclist ){
iOff += fts5GetVarint(&pDoclist[iOff], &iDelta);
iRowid += iDelta;
if( writer.bFirstRowidInPage ){
fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
writer.bFirstRowidInPage = 0;
fts5WriteDlidxAppend(p, &writer, iRowid);
|
| ︙ | ︙ | |||
224830 224831 224832 224833 224834 224835 224836 |
if( pHead->iPos!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
}
nTail = pHead->iter.nPoslist - pHead->iOff;
/* WRITEPOSLISTSIZE */
| > | | 226050 226051 226052 226053 226054 226055 226056 226057 226058 226059 226060 226061 226062 226063 226064 226065 |
if( pHead->iPos!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
}
nTail = pHead->iter.nPoslist - pHead->iOff;
/* WRITEPOSLISTSIZE */
assert_nc( tmp.n+nTail<=nTmp );
assert( tmp.n+nTail<=nTmp+nMerge*10 );
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
break;
}
fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
if( nTail>0 ){
|
| ︙ | ︙ | |||
225977 225978 225979 225980 225981 225982 225983 225984 225985 225986 225987 225988 225989 225990 | /************************************************************************* ************************************************************************** ** Below this point is the implementation of the fts5_decode() scalar ** function only. */ /* ** Decode a segment-data rowid from the %_data table. This function is ** the opposite of macro FTS5_SEGMENT_ROWID(). */ static void fts5DecodeRowid( i64 iRowid, /* Rowid from %_data table */ int *piSegid, /* OUT: Segment id */ | > | 227198 227199 227200 227201 227202 227203 227204 227205 227206 227207 227208 227209 227210 227211 227212 | /************************************************************************* ************************************************************************** ** Below this point is the implementation of the fts5_decode() scalar ** function only. */ #ifdef SQLITE_TEST /* ** Decode a segment-data rowid from the %_data table. This function is ** the opposite of macro FTS5_SEGMENT_ROWID(). */ static void fts5DecodeRowid( i64 iRowid, /* Rowid from %_data table */ int *piSegid, /* OUT: Segment id */ |
| ︙ | ︙ | |||
225999 226000 226001 226002 226003 226004 226005 226006 226007 226008 226009 226010 226011 226012 226013 226014 226015 226016 226017 226018 226019 226020 226021 226022 226023 226024 226025 226026 226027 226028 226029 226030 226031 |
iRowid >>= FTS5_DATA_HEIGHT_B;
*pbDlidx = (int)(iRowid & 0x0001);
iRowid >>= FTS5_DATA_DLI_B;
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
if( iSegid==0 ){
if( iKey==FTS5_AVERAGES_ROWID ){
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
}else{
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}");
}
}
else{
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}",
bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno
);
}
}
static void fts5DebugStructure(
int *pRc, /* IN/OUT: error code */
Fts5Buffer *pBuf,
Fts5Structure *p
){
int iLvl, iSeg; /* Iterate through levels, segments */
| > > > > | 227221 227222 227223 227224 227225 227226 227227 227228 227229 227230 227231 227232 227233 227234 227235 227236 227237 227238 227239 227240 227241 227242 227243 227244 227245 227246 227247 227248 227249 227250 227251 227252 227253 227254 227255 227256 227257 |
iRowid >>= FTS5_DATA_HEIGHT_B;
*pbDlidx = (int)(iRowid & 0x0001);
iRowid >>= FTS5_DATA_DLI_B;
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
if( iSegid==0 ){
if( iKey==FTS5_AVERAGES_ROWID ){
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
}else{
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}");
}
}
else{
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}",
bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno
);
}
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
static void fts5DebugStructure(
int *pRc, /* IN/OUT: error code */
Fts5Buffer *pBuf,
Fts5Structure *p
){
int iLvl, iSeg; /* Iterate through levels, segments */
|
| ︙ | ︙ | |||
226039 226040 226041 226042 226043 226044 226045 226046 226047 226048 226049 226050 226051 226052 226053 |
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}",
pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
);
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
}
}
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
** function appends a human-readable representation of the same object
** to the buffer passed as the second argument.
*/
| > > | 227265 227266 227267 227268 227269 227270 227271 227272 227273 227274 227275 227276 227277 227278 227279 227280 227281 |
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}",
pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
);
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
}
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
** function appends a human-readable representation of the same object
** to the buffer passed as the second argument.
*/
|
| ︙ | ︙ | |||
226064 226065 226066 226067 226068 226069 226070 226071 226072 226073 226074 226075 226076 226077 226078 |
*pRc = rc;
return;
}
fts5DebugStructure(pRc, pBuf, p);
fts5StructureRelease(p);
}
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain an "averages" record. This function
** appends a human-readable representation of record to the buffer passed
** as the second argument.
*/
| > > | 227292 227293 227294 227295 227296 227297 227298 227299 227300 227301 227302 227303 227304 227305 227306 227307 227308 |
*pRc = rc;
return;
}
fts5DebugStructure(pRc, pBuf, p);
fts5StructureRelease(p);
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain an "averages" record. This function
** appends a human-readable representation of record to the buffer passed
** as the second argument.
*/
|
| ︙ | ︙ | |||
226087 226088 226089 226090 226091 226092 226093 226094 226095 226096 226097 226098 226099 226100 226101 226102 226103 226104 226105 226106 226107 226108 226109 226110 226111 226112 226113 226114 226115 226116 226117 226118 |
while( i<nBlob ){
u64 iVal;
i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
zSpace = " ";
}
}
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
** after either the input buffer is exhausted or a 0 value is read.
**
** The return value is the number of bytes read from the input buffer.
*/
static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
int iOff = 0;
while( iOff<n ){
int iVal;
iOff += fts5GetVarint32(&a[iOff], iVal);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
}
return iOff;
}
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
** representation of the part of the doclist that is present to buffer
** pBuf.
**
** The return value is the number of bytes read from the input buffer.
| > > > > | 227317 227318 227319 227320 227321 227322 227323 227324 227325 227326 227327 227328 227329 227330 227331 227332 227333 227334 227335 227336 227337 227338 227339 227340 227341 227342 227343 227344 227345 227346 227347 227348 227349 227350 227351 227352 |
while( i<nBlob ){
u64 iVal;
i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
zSpace = " ";
}
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
** after either the input buffer is exhausted or a 0 value is read.
**
** The return value is the number of bytes read from the input buffer.
*/
static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
int iOff = 0;
while( iOff<n ){
int iVal;
iOff += fts5GetVarint32(&a[iOff], iVal);
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
}
return iOff;
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
** representation of the part of the doclist that is present to buffer
** pBuf.
**
** The return value is the number of bytes read from the input buffer.
|
| ︙ | ︙ | |||
226137 226138 226139 226140 226141 226142 226143 226144 226145 226146 226147 226148 226149 226150 226151 |
iDocid += iDelta;
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
}
}
return iOff;
}
/*
** This function is part of the fts5_decode() debugging function. It is
** only ever used with detail=none tables.
**
** Buffer (pData/nData) contains a doclist in the format used by detail=none
** tables. This function appends a human-readable version of that list to
** buffer pBuf.
| > > | 227371 227372 227373 227374 227375 227376 227377 227378 227379 227380 227381 227382 227383 227384 227385 227386 227387 |
iDocid += iDelta;
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
}
}
return iOff;
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is
** only ever used with detail=none tables.
**
** Buffer (pData/nData) contains a doclist in the format used by detail=none
** tables. This function appends a human-readable version of that list to
** buffer pBuf.
|
| ︙ | ︙ | |||
226178 226179 226180 226181 226182 226183 226184 226185 226186 226187 226188 226189 226190 226191 226192 |
zApp = "*";
}
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args (always 2) */
sqlite3_value **apVal /* Function arguments */
| > > | 227414 227415 227416 227417 227418 227419 227420 227421 227422 227423 227424 227425 227426 227427 227428 227429 227430 |
zApp = "*";
}
}
sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args (always 2) */
sqlite3_value **apVal /* Function arguments */
|
| ︙ | ︙ | |||
226387 226388 226389 226390 226391 226392 226393 226394 226395 226396 226397 226398 226399 226400 226401 |
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
fts5BufferFree(&s);
}
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
static void fts5RowidFunction(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args (always 2) */
sqlite3_value **apVal /* Function arguments */
| > > | 227625 227626 227627 227628 227629 227630 227631 227632 227633 227634 227635 227636 227637 227638 227639 227640 227641 |
if( rc==SQLITE_OK ){
sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
}else{
sqlite3_result_error_code(pCtx, rc);
}
fts5BufferFree(&s);
}
#endif /* SQLITE_TEST */
#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
static void fts5RowidFunction(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args (always 2) */
sqlite3_value **apVal /* Function arguments */
|
| ︙ | ︙ | |||
226421 226422 226423 226424 226425 226426 226427 226428 226429 226430 226431 226432 226433 226434 226435 226436 226437 226438 226439 226440 226441 226442 226443 226444 226445 226446 226447 226448 226449 226450 226451 226452 226453 226454 226455 226456 226457 226458 226459 226460 226461 |
}else{
sqlite3_result_error(pCtx,
"first arg to fts5_rowid() must be 'segment'" , -1
);
}
}
}
/*
** This is called as part of registering the FTS5 module with database
** connection db. It registers several user-defined scalar functions useful
** with FTS5.
**
** If successful, SQLITE_OK is returned. If an error occurs, some other
** SQLite error code is returned instead.
*/
static int sqlite3Fts5IndexInit(sqlite3 *db){
int rc = sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_decode_none", 2,
SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
);
}
return rc;
}
static int sqlite3Fts5IndexReset(Fts5Index *p){
assert( p->pStruct==0 || p->iStructVersion!=0 );
if( fts5IndexDataVersion(p)!=p->iStructVersion ){
fts5StructureInvalidate(p);
| > > > > > > | 227661 227662 227663 227664 227665 227666 227667 227668 227669 227670 227671 227672 227673 227674 227675 227676 227677 227678 227679 227680 227681 227682 227683 227684 227685 227686 227687 227688 227689 227690 227691 227692 227693 227694 227695 227696 227697 227698 227699 227700 227701 227702 227703 227704 227705 227706 227707 |
}else{
sqlite3_result_error(pCtx,
"first arg to fts5_rowid() must be 'segment'" , -1
);
}
}
}
#endif /* SQLITE_TEST */
/*
** This is called as part of registering the FTS5 module with database
** connection db. It registers several user-defined scalar functions useful
** with FTS5.
**
** If successful, SQLITE_OK is returned. If an error occurs, some other
** SQLite error code is returned instead.
*/
static int sqlite3Fts5IndexInit(sqlite3 *db){
#ifdef SQLITE_TEST
int rc = sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_decode_none", 2,
SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
);
}
return rc;
#else
return SQLITE_OK;
UNUSED_PARAM(db);
#endif
}
static int sqlite3Fts5IndexReset(Fts5Index *p){
assert( p->pStruct==0 || p->iStructVersion!=0 );
if( fts5IndexDataVersion(p)!=p->iStructVersion ){
fts5StructureInvalidate(p);
|
| ︙ | ︙ | |||
226483 226484 226485 226486 226487 226488 226489 226490 226491 226492 226493 226494 226495 226496 226497 | /* ** 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 fts5 code are activated - conditions that are ** only true if it is guaranteed that the fts5 database is not corrupt. */ SQLITE_API int sqlite3_fts5_may_be_corrupt = 1; typedef struct Fts5Auxdata Fts5Auxdata; typedef struct Fts5Auxiliary Fts5Auxiliary; typedef struct Fts5Cursor Fts5Cursor; typedef struct Fts5FullTable Fts5FullTable; typedef struct Fts5Sorter Fts5Sorter; | > > | 227729 227730 227731 227732 227733 227734 227735 227736 227737 227738 227739 227740 227741 227742 227743 227744 227745 | /* ** 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 fts5 code are activated - conditions that are ** only true if it is guaranteed that the fts5 database is not corrupt. */ #ifdef SQLITE_DEBUG SQLITE_API int sqlite3_fts5_may_be_corrupt = 1; #endif typedef struct Fts5Auxdata Fts5Auxdata; typedef struct Fts5Auxiliary Fts5Auxiliary; typedef struct Fts5Cursor Fts5Cursor; typedef struct Fts5FullTable Fts5FullTable; typedef struct Fts5Sorter Fts5Sorter; |
| ︙ | ︙ | |||
228408 228409 228410 228411 228412 228413 228414 |
iBest = i;
}
}
if( iBest<0 ) break;
nInst++;
if( nInst>=pCsr->nInstAlloc ){
| | | > > | 229656 229657 229658 229659 229660 229661 229662 229663 229664 229665 229666 229667 229668 229669 229670 229671 229672 229673 229674 229675 229676 229677 229678 |
iBest = i;
}
}
if( iBest<0 ) break;
nInst++;
if( nInst>=pCsr->nInstAlloc ){
int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
aInst = (int*)sqlite3_realloc64(
pCsr->aInst, nNewSize*sizeof(int)*3
);
if( aInst ){
pCsr->aInst = aInst;
pCsr->nInstAlloc = nNewSize;
}else{
nInst--;
rc = SQLITE_NOMEM;
break;
}
}
aInst = &pCsr->aInst[3 * (nInst-1)];
aInst[0] = iBest;
|
| ︙ | ︙ | |||
229249 229250 229251 229252 229253 229254 229255 |
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);
| | | 230499 230500 230501 230502 230503 230504 230505 230506 230507 230508 230509 230510 230511 230512 230513 |
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-06-04 23:26:56 1c71de43dbc68002c4a6229e7efffb019655baff67a51fe922571fe420c95835", -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){
|
| ︙ | ︙ | |||
234175 234176 234177 234178 234179 234180 234181 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | | | | 235425 235426 235427 235428 235429 235430 235431 235432 235433 235434 235435 235436 235437 235438 |
#endif
return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
#if __LINE__!=235432
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID "2021-06-07 00:41:18 2aa9368b63b42ac7c700516f109edcc6098c12b850eae591afed4e51a3f4alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/
|
Changes to src/sqlite3.h.
| ︙ | ︙ | |||
119 120 121 122 123 124 125 | ** 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()]. */ | | | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** 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.36.0" #define SQLITE_VERSION_NUMBER 3036000 #define SQLITE_SOURCE_ID "2021-06-07 00:41:18 2aa9368b63b42ac7c700516f109edcc6098c12b850eae591afed4e51a3f41819" /* ** 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 |
| ︙ | ︙ | |||
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 | > > > > > > > > > > > > > > > > > | 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 | ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** </ul> ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode ** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that ** currently has an SQL transaction open on the database. It is set to 0 if ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes. ** </ul> ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]] ** Used by the cksmvfs VFS module only. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 |
| ︙ | ︙ | |||
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 #define SQLITE_FCNTL_CKPT_DONE 37 #define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_CKPT_START 39 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO | > > | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 #define SQLITE_FCNTL_LOCK_TIMEOUT 34 #define SQLITE_FCNTL_DATA_VERSION 35 #define SQLITE_FCNTL_SIZE_LIMIT 36 #define SQLITE_FCNTL_CKPT_DONE 37 #define SQLITE_FCNTL_RESERVE_BYTES 38 #define SQLITE_FCNTL_CKPT_START 39 #define SQLITE_FCNTL_EXTERNAL_READER 40 #define SQLITE_FCNTL_CKSM_FILE 41 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO |
| ︙ | ︙ | |||
4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 | ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement ** METHOD: sqlite3_stmt ** | > > > > > > > > > | 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 | ** sqlite3_stmt_readonly() to return true since, while those statements ** change the configuration of a database connection, they do not make ** changes to the content of the database files on disk. ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. ** ** ^This routine returns false if there is any possibility that the ** statement might change the database file. ^A false return does ** not guarantee that the statement will change the database file. ** ^For example, an UPDATE statement might have a WHERE clause that ** makes it a no-op, but the sqlite3_stmt_readonly() result would still ** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a ** read-only no-op if the table already exists, but ** sqlite3_stmt_readonly() still returns false for such a statement. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement ** METHOD: sqlite3_stmt ** |
| ︙ | ︙ | |||
4344 4345 4346 4347 4348 4349 4350 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** | | | > | | | | < | | > > > | < | > > | 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 | ** that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occurs at byte offsets less than ** the value of the fourth parameter then the resulting string value will ** contain embedded NULs. The result of expressions involving strings ** with embedded NULs is undefined. ** ** ^The fifth argument to the BLOB and string binding interfaces controls ** or indicates the lifetime of the object referenced by the third parameter. ** ^These three options exist: ** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished ** with it may be passed. ^It is called to dispose of the BLOB or string even ** if the call to the bind API fails, except the destructor is not called if ** the third parameter is a NULL pointer or the fourth parameter is negative. ** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that ** the application remains responsible for disposing of the object. ^In this ** case, the object and the provided pointer to it must remain valid until ** either the prepared statement is finalized or the same SQL parameter is ** bound to something else, whichever occurs sooner. ** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the ** object is to be copied prior to the return from sqlite3_bind_*(). ^The ** object and pointer to it must remain valid until then. ^SQLite will then ** manage the lifetime of its private copy. ** ** ^The sixth argument to sqlite3_bind_text64() must be one of ** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE] ** to specify the encoding of the text in the third parameter. If ** the sixth argument to sqlite3_bind_text64() is not one of the ** allowed values shown above, or if the text encoding is different ** from the encoding specified by the sixth parameter, then the behavior |
| ︙ | ︙ | |||
5097 5098 5099 5100 5101 5102 5103 | ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** | < < | 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 | ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. ** ** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] ** flag, which if present prevents the function from being invoked from ** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions, ** index expressions, or the WHERE clause of partial indexes. ** ** For best security, the [SQLITE_DIRECTONLY] flag is recommended for ** all application-defined SQL functions that do not need to be ** used inside of triggers, view, CHECK constraints, or other elements of ** the database schema. This flags is especially recommended for SQL ** functions that have side effects or reveal internal application state. ** Without this flag, an attacker might be able to modify the schema of ** a database file to include invocations of the function with parameters ** chosen by the attacker, which the application will then execute when ** the database file is opened and read. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ ** ** ^The sixth, seventh and eighth parameters passed to the three ** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or |
| ︙ | ︙ | |||
7775 7776 7777 7778 7779 7780 7781 | #define SQLITE_TESTCTRL_IMPOSTER 25 #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 | > | | 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 | #define SQLITE_TESTCTRL_IMPOSTER 25 #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_LAST 32 /* 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, |
| ︙ | ︙ | |||
9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 |
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
#endif
/*
** CAPI3REF: Low-level system error code
** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
| > > > > > > > > > > | 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 |
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** When the [sqlite3_blob_write()] API is used to update a blob column,
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
** in this case the new values are not available. In this case, when a
** callback made with op==SQLITE_DELETE is actuall a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
** pre-update hook is being invoked for some other reason, including a
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
**
** See also: [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
sqlite3 *db, /* Database handle */
int op, /* SQLITE_UPDATE, DELETE or INSERT */
char const *zDb, /* Database name */
char const *zName, /* Table name */
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
),
void*
);
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
#endif
/*
** CAPI3REF: Low-level system error code
** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
|
| ︙ | ︙ | |||
9785 9786 9787 9788 9789 9790 9791 | ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. ** | | | | 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 | ** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy ** of the database exists. ** ** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the ** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory ** allocation error occurs. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API unsigned char *sqlite3_serialize( sqlite3 *db, /* The database connection */ const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ ); |
| ︙ | ︙ | |||
9837 9838 9839 9840 9841 9842 9843 | ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** | | | | 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 | ** database is currently in a read transaction or is involved in a backup ** operation. ** ** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the ** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then ** [sqlite3_free()] is invoked on argument P prior to returning. ** ** This interface is omitted if SQLite is compiled with the ** [SQLITE_OMIT_DESERIALIZE] option. */ SQLITE_API int sqlite3_deserialize( sqlite3 *db, /* The database connection */ const char *zSchema, /* Which DB to reopen with the deserialization */ unsigned char *pData, /* The serialized database content */ sqlite3_int64 szDb, /* Number bytes in the deserialization */ sqlite3_int64 szBuf, /* Total size of buffer pData[] */ |
| ︙ | ︙ | |||
10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 | ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object ** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 | ** ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPIREF: Conigure a Session Object ** METHOD: sqlite3_session ** ** This method is used to configure a session object after it has been ** created. At present the only valid value for the second parameter is ** [SQLITE_SESSION_OBJCONFIG_SIZE]. ** ** Arguments for sqlite3session_object_config() ** ** The following values may passed as the the 4th parameter to ** sqlite3session_object_config(). ** ** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd> ** This option is used to set, clear or query the flag that enables ** the [sqlite3session_changeset_size()] API. Because it imposes some ** computational overhead, this API is disabled by default. Argument ** pArg must point to a value of type (int). If the value is initially ** 0, then the sqlite3session_changeset_size() API is disabled. If it ** is greater than 0, then the same API is enabled. Or, if the initial ** value is less than zero, no change is made. In all cases the (int) ** variable is set to 1 if the sqlite3session_changeset_size() API is ** enabled following the current call, or 0 otherwise. ** ** It is an error (SQLITE_MISUSE) to attempt to modify this setting after ** the first table has been attached to the session object. */ SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); /* */ #define SQLITE_SESSION_OBJCONFIG_SIZE 1 /* ** CAPI3REF: Enable Or Disable A Session Object ** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When |
| ︙ | ︙ | |||
10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 | */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Load The Difference Between Tables Into A Session ** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it | > > > > > > > > > > > > > > > > | 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 | */ SQLITE_API int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Return An Upper-limit For The Size Of The Changeset ** METHOD: sqlite3_session ** ** By default, this function always returns 0. For it to return ** a useful result, the sqlite3_session object must have been configured ** to enable this API using sqlite3session_object_config() with the ** SQLITE_SESSION_OBJCONFIG_SIZE verb. ** ** When enabled, this function returns an upper limit, in bytes, for the size ** of the changeset that might be produced if sqlite3session_changeset() were ** called. The final changeset size might be equal to or smaller than the ** size in bytes returned by this function. */ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession); /* ** CAPI3REF: Load The Difference Between Tables Into A Session ** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the ** [sqlite3session_attach()] function. If zTbl does not exist, or if it |
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
/*
** Generate stats for the email notification subsystem.
*/
void stats_for_email(void){
const char *zDest = db_get("email-send-method",0);
int nSub, nASub, nPend, nDPend;
const char *zDir, *zDb, *zCmd, *zRelay;
@ <tr><th>Outgoing Email:</th><td>
if( fossil_strcmp(zDest,"pipe")==0
&& (zCmd = db_get("email-send-command",0))!=0
){
@ Piped to command "%h(zCmd)"
}else
if( fossil_strcmp(zDest,"db")==0
| > | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/*
** Generate stats for the email notification subsystem.
*/
void stats_for_email(void){
const char *zDest = db_get("email-send-method",0);
int nSub, nASub, nPend, nDPend;
const char *zDir, *zDb, *zCmd, *zRelay;
int iCutoff;
@ <tr><th>Outgoing Email:</th><td>
if( fossil_strcmp(zDest,"pipe")==0
&& (zCmd = db_get("email-send-command",0))!=0
){
@ Piped to command "%h(zCmd)"
}else
if( fossil_strcmp(zDest,"db")==0
|
| ︙ | ︙ | |||
108 109 110 111 112 113 114 115 |
@ </td></tr>
if( g.perm.Admin ){
@ <tr><th><a href="%R/subscribers">Subscribers:</a></th><td>
}else{
@ <tr><th>Subscribers:</th><td>
}
nSub = db_int(0, "SELECT count(*) FROM subscriber");
nASub = db_int(0, "SELECT count(*) FROM subscriber WHERE sverified"
| > | > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
@ </td></tr>
if( g.perm.Admin ){
@ <tr><th><a href="%R/subscribers">Subscribers:</a></th><td>
}else{
@ <tr><th>Subscribers:</th><td>
}
nSub = db_int(0, "SELECT count(*) FROM subscriber");
iCutoff = db_get_int("email-renew-cutoff",0);
nASub = db_int(0, "SELECT count(*) FROM subscriber WHERE sverified"
" AND NOT sdonotcall AND length(ssub)>1"
" AND lastContact>=%d;", iCutoff);
@ %,d(nASub) active, %,d(nSub) total
@ </td></tr>
}
/*
** WEBPAGE: stat
**
|
| ︙ | ︙ |
Changes to src/tag.c.
| ︙ | ︙ | |||
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
}
assert( blob_is_reset(&ctrl) );
if( g.localOpen ){
manifest_to_disk(rid);
}
}
/*
** COMMAND: tag
**
** Usage: %fossil tag SUBCOMMAND ...
**
** Run various subcommands to control tags and properties.
**
| > > > > > > > > > > > > > > > > > > > > > | | > | | > | | > | | | | | > > > > | | | | > > | > | < < | > > > | > > > | | | | > > > | | > > > > > > > > | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
manifest_crosslink(nrid, &ctrl, MC_PERMIT_HOOKS);
}
assert( blob_is_reset(&ctrl) );
if( g.localOpen ){
manifest_to_disk(rid);
}
}
/*
** If zTag is NULL or valid for use as a tag for the `tag add` and
** `tag cancel` commands, returns without side effects, else emits a
** fatal error message. We reject certain prefixes to avoid that
** clients cause undue grief by improperly tagging artifacts as being,
** e.g., wiki pages or tickets.
**
** Note that we intentionally allow the "sym-" prefix, partly for
** historical compatibility and partly because it can be applied
** properly, whereas the other reserved name types have special
** meanings for fossil and cannot be sensibly manually manipulated.
*/
static void tag_cmd_tagname_check(const char *zTag){
if(zTag && *zTag &&
(strncmp(zTag,"wiki-",5)==0
|| strncmp(zTag,"tkt-",4)==0
|| strncmp(zTag,"event-",6)==0)){
fossil_fatal("Invalid prefix for tag name: %s", zTag);
}
}
/*
** COMMAND: tag
**
** Usage: %fossil tag SUBCOMMAND ...
**
** Run various subcommands to control tags and properties.
**
** > fossil tag add ?OPTIONS? TAGNAME ARTIFACT-ID ?VALUE?
**
** Add a new tag or property to an artifact referenced by
** ARTIFACT-ID. For checkins, the tag will be usable instead
** of a CHECK-IN in commands such as update and merge. If the
** --propagate flag is present and ARTIFACT-ID refers to a
** wiki page, forum post, technote, or check-in, the tag
** propagates to all descendants of that artifact.
**
** Options:
** --raw Raw tag name. Ignored for
** non-CHECK-IN artifacts.
** --propagate Propagating tag.
** --date-override DATETIME Set date and time added.
** --user-override USER Name USER when adding the tag.
** -n|--dryrun Display the tag text, but do not
** actually insert it into the database.
**
** The --date-override and --user-override options support
** importing history from other SCM systems. DATETIME has
** the form 'YYYY-MMM-DD HH:MM:SS'.
**
** Note that fossil uses some tag prefixes internally and this
** command will reject tags with these prefixes to avoid
** causing problems or confusion: "wiki-", "tkt-", "event-".
**
** > fossil tag cancel ?--raw? TAGNAME ARTIFACT-ID
**
** Remove the tag TAGNAME from the artifact referenced by
** ARTIFACT-ID, and also remove the propagation of the tag to
** any descendants. Use the the -n|--dryrun option to see
** what would have happened. Certain tag name prefixes are
** forbidden, as documented for the 'add' subcommand.
**
** Options:
** --raw Raw tag name. Ignored for
** non-CHECK-IN artifacts.
** --date-override DATETIME Set date and time deleted.
** --user-override USER Name USER when deleting the tag.
** -n|--dryrun Display the control artifact, but do
** not insert it into the database.
**
** > fossil tag find ?OPTIONS? TAGNAME
**
** List all objects that use TAGNAME.
**
** Options:
** --raw Interprets tag as a raw name instead of a
** branch name and matches any type of artifact.
** Changes the output to include only the
** hashes of matching objects.
** -t|--type TYPE One of: ci (check-in), w (wiki),
** e (event/technote), f (forum post),
** t (ticket). Default is all types. Ignored
** if --raw is used.
** -n|--limit N Limit to N results.
**
** > fossil tag list|ls ?OPTIONS? ?ARTIFACT-ID?
**
** List all tags or, if ARTIFACT-ID is supplied, all tags and
** their values for that artifact. The tagtype option accepts
** one of: propagated, singleton, cancel. For historical
** scripting compatibility, the internal tag types "wiki-",
** "tkt-", and "event-" (technote) are elided by default
** unless the --raw or --prefix options are used.
**
** Options:
** --raw List raw names of tags
** --tagtype TYPE List only tags of type TYPE, which must
** be one of: cancel, singleton, propagated
** -v|--inverse Inverse the meaning of --tagtype TYPE.
** --prefix List only tags with the given prefix.
** Fossil-internal prefixes include "sym-"
** (branch name), "wiki-", "event-"
** (technote), and "tkt-" (ticket). The
** prefix is stripped from the resulting
** list unless --raw is provided. Ignored if
** ARTIFACT-ID is provided.
**
** The option --raw allows the manipulation of all types of tags
** used for various internal purposes in fossil. It also shows
** "cancel" tags for the "find" and "list" subcommands. You should
** not use this option to make changes unless you are sure what
** you are doing.
**
|
| ︙ | ︙ | |||
459 460 461 462 463 464 465 |
goto tag_cmd_usage;
}
if( strncmp(g.argv[2],"add",n)==0 ){
char *zValue;
int dryRun = 0;
int fRaw = find_option("raw","",0)!=0;
| | > > > | > > > > > > > > > > > > > | | > > > | > > > > > > > > > > > > > | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
goto tag_cmd_usage;
}
if( strncmp(g.argv[2],"add",n)==0 ){
char *zValue;
int dryRun = 0;
int fRaw = find_option("raw","",0)!=0;
const char *zPrefix = "";
int fPropagate = find_option("propagate","",0)!=0;
const char *zDateOvrd = find_option("date-override",0,1);
const char *zUserOvrd = find_option("user-override",0,1);
const char *zTag;
const char *zObjId;
int objType;
if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
if( g.argc!=5 && g.argc!=6 ){
usage("add ?options? TAGNAME ARTIFACT-ID ?VALUE?");
}
zTag = g.argv[3];
tag_cmd_tagname_check(zTag);
zObjId = g.argv[4];
zValue = g.argc==6 ? g.argv[5] : 0;
objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0));
switch(objType){
case 0:
fossil_fatal("Cannot resolve artifact ID: %s", zObjId);
break;
case CFTYPE_MANIFEST:
zPrefix = fRaw ? "" : "sym-";
break;
default: break;
}
db_begin_transaction();
tag_add_artifact(zPrefix, zTag, zObjId, zValue,
1+fPropagate+dryRun,zDateOvrd,zUserOvrd);
db_end_transaction(0);
}else
if( strncmp(g.argv[2],"branch",n)==0 ){
fossil_fatal("the \"fossil tag branch\" command is discontinued\n"
"Use the \"fossil branch new\" command instead.");
}else
if( strncmp(g.argv[2],"cancel",n)==0 ){
int dryRun = 0;
int fRaw = find_option("raw","",0)!=0;
const char *zPrefix = "";
const char *zDateOvrd = find_option("date-override",0,1);
const char *zUserOvrd = find_option("user-override",0,1);
const char *zTag;
const char *zObjId;
int objType;
if( find_option("dryrun","n",0)!=0 ) dryRun = TAG_ADD_DRYRUN;
if( g.argc!=5 ){
usage("cancel ?options? TAGNAME ARTIFACT-ID");
}
zTag = g.argv[3];
tag_cmd_tagname_check(zTag);
zObjId = g.argv[4];
objType = whatis_rid_type(symbolic_name_to_rid(zObjId, 0));
switch(objType){
case 0:
fossil_fatal("Cannot resolve artifact ID: %s", zObjId);
break;
case CFTYPE_MANIFEST:
zPrefix = fRaw ? "" : "sym-";
break;
default: break;
}
db_begin_transaction();
tag_add_artifact(zPrefix, zTag, zObjId, 0, dryRun,
zDateOvrd, zUserOvrd);
db_end_transaction(0);
}else
if( strncmp(g.argv[2],"find",n)==0 ){
Stmt q;
int fRaw = find_option("raw","",0)!=0;
|
| ︙ | ︙ | |||
524 525 526 527 528 529 530 |
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}else{
| | > > > | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%s\n", db_column_text(&q, 0));
}
db_finalize(&q);
}else{
int tagid = db_int(0, "SELECT tagid FROM tag "
"WHERE tagname='%s%q'",
(zType && 'c'==zType[0])
? "sym-" : ""/*safe-for-%s*/,
g.argv[3]);
if( tagid>0 ){
blob_append_sql(&sql,
"%s"
" AND event.type GLOB '%q'"
" AND blob.rid IN ("
" SELECT rid FROM tagxref"
|
| ︙ | ︙ | |||
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 |
}else
if(( strncmp(g.argv[2],"list",n)==0 )||( strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
const int fRaw = find_option("raw","",0)!=0;
const char *zTagType = find_option("tagtype","t",1);
const int fInverse = find_option("inverse","v",0)!=0;
int nTagType = fRaw ? -1 : 0;
if( zTagType!=0 ){
int l = strlen(zTagType);
if( strncmp(zTagType,"cancel",l)==0 ){
nTagType = 0;
}else if( strncmp(zTagType,"singleton",l)==0 ){
nTagType = 1;
}else if( strncmp(zTagType,"propagated",l)==0 ){
nTagType = 2;
}else{
fossil_fatal("unrecognized tag type");
}
}
if( g.argc==3 ){
db_prepare(&q,
"SELECT tagname FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype%s%d)"
| > > > > | | > > > > | > > > > > > > > > > > > > > > > > > > < | | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 |
}else
if(( strncmp(g.argv[2],"list",n)==0 )||( strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
const int fRaw = find_option("raw","",0)!=0;
const char *zTagType = find_option("tagtype","t",1);
const int fInverse = find_option("inverse","v",0)!=0;
const char *zTagPrefix = find_option("prefix","",1);
int nTagType = fRaw ? -1 : 0;
if( zTagType!=0 ){
int l = strlen(zTagType);
if( strncmp(zTagType,"cancel",l)==0 ){
nTagType = 0;
}else if( strncmp(zTagType,"singleton",l)==0 ){
nTagType = 1;
}else if( strncmp(zTagType,"propagated",l)==0 ){
nTagType = 2;
}else{
fossil_fatal("unrecognized tag type");
}
}
if( g.argc==3 ){
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
db_prepare(&q,
"SELECT tagname FROM tag"
" WHERE EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=tag.tagid"
" AND tagtype%s%d)"
" AND CASE WHEN %Q IS NULL THEN 1 ELSE tagname GLOB %Q||'*' "
" END ORDER BY tagname",
zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
nTagType, zTagPrefix, zTagPrefix
);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
if( fRaw ){
fossil_print("%s\n", zName);
}else if( nTagPrefix>0 ){
assert(db_column_bytes(&q,0)>=nTagPrefix);
fossil_print("%s\n", &zName[nTagPrefix]);
}else if( strncmp(zName, "sym-", 4)==0 ){
fossil_print("%s\n", &zName[4]);
}
}
db_finalize(&q);
}else if( g.argc==4 ){
char const *zObjId = g.argv[3];
const int rid = name_to_rid(zObjId);
const int objType = whatis_rid_type(rid);
int nTagOffset = 0;
zTagPrefix = 0;
if(objType<=0){
fossil_fatal("Cannot resolve artifact ID: %s", zObjId);
}else if(fRaw==0){
/* Figure out the tag prefix to strip */
switch(objType){
case CFTYPE_MANIFEST: zTagPrefix = "sym-"; break;
case CFTYPE_WIKI: zTagPrefix = "wiki-"; break;
case CFTYPE_TICKET: zTagPrefix = "tkt-"; break;
case CFTYPE_EVENT: zTagPrefix = "event-"; break;
default: break;
}
if(zTagPrefix!=0){
nTagOffset = (int)strlen(zTagPrefix);
}
}
db_prepare(&q,
"SELECT tagname, value FROM tagxref, tag"
" WHERE tagxref.rid=%d AND tagxref.tagid=tag.tagid"
" AND tagtype%s%d"
" ORDER BY tagname",
rid,
zTagType!=0 ? (fInverse!=0?"<>":"=") : ">"/*safe-for-%s*/,
nTagType
);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zValue = db_column_text(&q, 1);
if( zTagPrefix && strncmp(zName, zTagPrefix, nTagOffset)==0 ){
zName += nTagOffset;
}
if( zValue && zValue[0] ){
fossil_print("%s=%s\n", zName, zValue);
}else{
fossil_print("%s\n", zName);
}
}
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
1273 1274 1275 1276 1277 1278 1279 |
/*
** Tag match expression type code.
*/
typedef enum {
MS_EXACT, /* Matches a single tag by exact string comparison. */
MS_GLOB, /* Matches tags against a list of GLOB patterns. */
MS_LIKE, /* Matches tags against a list of LIKE patterns. */
| | > > | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 |
/*
** Tag match expression type code.
*/
typedef enum {
MS_EXACT, /* Matches a single tag by exact string comparison. */
MS_GLOB, /* Matches tags against a list of GLOB patterns. */
MS_LIKE, /* Matches tags against a list of LIKE patterns. */
MS_REGEXP, /* Matches tags against a list of regular expressions. */
MS_BRLIST, /* Same as REGEXP, except the regular expression is a list
** of branch names */
} MatchStyle;
/*
** Quote a tag string by surrounding it with double quotes and preceding
** internal double quotes and backslashes with backslashes.
*/
static const char *tagQuote(
|
| ︙ | ︙ | |||
1308 1309 1310 1311 1312 1313 1314 | return blob_str(&blob); } /* ** Construct the tag match SQL expression. ** ** This function is adapted from glob_expr() to support the MS_EXACT, MS_GLOB, | > > | | 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 | return blob_str(&blob); } /* ** Construct the tag match SQL expression. ** ** This function is adapted from glob_expr() to support the MS_EXACT, MS_GLOB, ** MS_LIKE, MS_REGEXP, and MS_BRLIST match styles. ** ** For MS_EXACT, the returned expression ** checks for integer match against the tag ID which is looked up directly by ** this function. For the other modes, the returned SQL expression performs ** string comparisons against the tag names, so it is necessary to join against ** the tag table to access the "tagname" column. ** ** Each pattern is adjusted to to start with "sym-" and be anchored at end. ** |
| ︙ | ︙ | |||
1370 1371 1372 1373 1374 1375 1376 |
}else if( matchStyle==MS_LIKE ){
zStart = "(";
zDelimiter = " OR ";
zEnd = ")";
zPrefix = "tagname LIKE 'sym-";
zSuffix = "'";
zIntro = "SQL LIKE pattern ";
| | > > > > > > > | 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 |
}else if( matchStyle==MS_LIKE ){
zStart = "(";
zDelimiter = " OR ";
zEnd = ")";
zPrefix = "tagname LIKE 'sym-";
zSuffix = "'";
zIntro = "SQL LIKE pattern ";
}else if( matchStyle==MS_REGEXP ){
zStart = "(tagname REGEXP '^sym-(";
zDelimiter = "|";
zEnd = ")$')";
zPrefix = "";
zSuffix = "";
zIntro = "regular expression ";
}else/* if( matchStyle==MS_BRLIST )*/{
zStart = "tagname IN ('sym-";
zDelimiter = "','sym-";
zEnd = "')";
zPrefix = "";
zSuffix = "";
zIntro = "any of ";
}
/* Convert the list of matches into an SQL expression and text description. */
blob_zero(&expr);
blob_zero(&desc);
blob_zero(&err);
while( 1 ){
|
| ︙ | ︙ | |||
1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 |
/* Interpet the tag style string. */
if( fossil_stricmp(zMatchStyle, "glob")==0 ){
matchStyle = MS_GLOB;
}else if( fossil_stricmp(zMatchStyle, "like")==0 ){
matchStyle = MS_LIKE;
}else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
matchStyle = MS_REGEXP;
}else{
/* For exact maching, inhibit links to the selected tag. */
zThisTag = zTagName;
Th_Store("current_checkin", zTagName);
}
/* Display a checkbox to enable/disable display of related check-ins. */
| > > | 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 |
/* Interpet the tag style string. */
if( fossil_stricmp(zMatchStyle, "glob")==0 ){
matchStyle = MS_GLOB;
}else if( fossil_stricmp(zMatchStyle, "like")==0 ){
matchStyle = MS_LIKE;
}else if( fossil_stricmp(zMatchStyle, "regexp")==0 ){
matchStyle = MS_REGEXP;
}else if( fossil_stricmp(zMatchStyle, "brlist")==0 ){
matchStyle = MS_BRLIST;
}else{
/* For exact maching, inhibit links to the selected tag. */
zThisTag = zTagName;
Th_Store("current_checkin", zTagName);
}
/* Display a checkbox to enable/disable display of related check-ins. */
|
| ︙ | ︙ | |||
1901 1902 1903 1904 1905 1906 1907 |
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n",
TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
);
tmFlags |= TIMELINE_UNHIDE;
zType = "ci";
disableY = 1;
}
| | < < < | 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 |
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=pid)\n",
TAG_BRANCH, TAG_BRANCH, TAG_BRANCH, TAG_BRANCH
);
tmFlags |= TIMELINE_UNHIDE;
zType = "ci";
disableY = 1;
}
if( bisectLocal && cgi_is_loopback(g.zIpAddr) && db_open_local(0) ){
int iCurrent = db_lget_int("checkout",0);
char *zPerm = bisect_permalink();
bisect_create_bilog_table(iCurrent, 0, 1);
tmFlags |= TIMELINE_UNHIDE | TIMELINE_BISECT | TIMELINE_FILLGAPS;
zType = "ci";
disableY = 1;
style_submenu_element("Permalink", "%R/timeline?bid=%z", zPerm);
|
| ︙ | ︙ | |||
2555 2556 2557 2558 2559 2560 2561 |
blob_appendf(&desc, " occurring around %h.<br />", zCirca);
}
if( zSearch ){
blob_appendf(&desc, " matching \"%h\"", zSearch);
}
if( g.perm.Hyperlink ){
static const char *const azMatchStyles[] = {
| | > | 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 |
blob_appendf(&desc, " occurring around %h.<br />", zCirca);
}
if( zSearch ){
blob_appendf(&desc, " matching \"%h\"", zSearch);
}
if( g.perm.Hyperlink ){
static const char *const azMatchStyles[] = {
"exact", "Exact", "glob", "Glob", "like", "Like", "regexp", "Regexp",
"brlist", "List"
};
double rDate;
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
zDate = mprintf("%s", (zAfter ? zAfter : zBefore));
}
if( zDate ){
|
| ︙ | ︙ |
Changes to src/undo.c.
| ︙ | ︙ | |||
267 268 269 270 271 272 273 |
** Save the current content of the file zPathname so that it
** will be undoable. The name is relative to the root of the
** tree.
*/
void undo_save(const char *zPathname){
if( undoDisable ) return;
if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){
| | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
** Save the current content of the file zPathname so that it
** will be undoable. The name is relative to the root of the
** tree.
*/
void undo_save(const char *zPathname){
if( undoDisable ) return;
if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){
fossil_fatal("failed to save undo information for path: %s",
zPathname);
}
}
/*
** Possibly save the current content of the file zPathname so
** that it will be undoable. The name is relative to the root
|
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
636 637 638 639 640 641 642 | ** reasonable basename of a local clone of that repository. ** ** * If the URL has a path, use the tail of the path, with any suffix ** elided. ** ** * If the URL is just a domain name, without a path, then use the ** first element of the domain name, except skip over "www." if | | | > > > > > | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
** reasonable basename of a local clone of that repository.
**
** * If the URL has a path, use the tail of the path, with any suffix
** elided.
**
** * If the URL is just a domain name, without a path, then use the
** first element of the domain name, except skip over "www." if
** present and if there is a ".com" or ".org" or similar suffix.
**
** The string returned is obtained from fossil_malloc(). NULL might be
** returned if there is an error.
*/
char *url_to_repo_basename(const char *zUrl){
const char *zTail = 0;
int i;
if( zUrl==0 ) return 0;
for(i=0; zUrl[i]; i++){
if( zUrl[i]=='?' ) break;
if( (zUrl[i]=='/' || zUrl[i]=='@') && zUrl[i+1]!=0 ) zTail = &zUrl[i+1];
}
if( zTail==0 ) return 0;
if( sqlite3_strnicmp(zTail, "www.", 4)==0 && strchr(zTail+4,'.')!=0 ){
/* Remove the "www." prefix if there are more "." characters later.
** But don't remove the "www." prefix if what follows is the suffix.
** forum:/forumpost/74e111a2ee */
zTail += 4;
}
if( zTail[0]==0 ) return 0;
for(i=0; zTail[i] && zTail[i]!='.' && zTail[i]!='?'; i++){}
if( i==0 ) return 0;
return mprintf("%.*s", i, zTail);
}
/*
|
| ︙ | ︙ |
Changes to src/util.c.
| ︙ | ︙ | |||
54 55 56 57 58 59 60 |
}
/*
** Malloc and free routines that cannot fail
*/
void *fossil_malloc(size_t n){
void *p = malloc(n==0 ? 1 : n);
| | | | | 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 |
}
/*
** Malloc and free routines that cannot fail
*/
void *fossil_malloc(size_t n){
void *p = malloc(n==0 ? 1 : n);
if( p==0 ) fossil_fatal("out of memory");
return p;
}
void *fossil_malloc_zero(size_t n){
void *p = malloc(n==0 ? 1 : n);
if( p==0 ) fossil_fatal("out of memory");
memset(p, 0, n);
return p;
}
void fossil_free(void *p){
free(p);
}
void *fossil_realloc(void *p, size_t n){
p = realloc(p, n);
if( p==0 ) fossil_fatal("out of memory");
return p;
}
void fossil_secure_zero(void *p, size_t n){
volatile unsigned char *vp = (volatile unsigned char *)p;
size_t i;
if( p==0 ) return;
|
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
assert( pageSize%2==0 );
#if defined(_WIN32)
p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if( p==NULL ){
| | | | | | 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 |
fossil_get_page_size(&pageSize);
assert( pageSize>0 );
assert( pageSize%2==0 );
#if defined(_WIN32)
p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if( p==NULL ){
fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
}
if( !VirtualLock(p, pageSize) ){
fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
}
#elif defined(USE_MMAN_H)
p = mmap(0, pageSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if( p==MAP_FAILED ){
fossil_fatal("mmap failed: %d\n", errno);
}
if( mlock(p, pageSize) ){
fossil_fatal("mlock failed: %d\n", errno);
}
#else
p = fossil_malloc(pageSize);
#endif
fossil_secure_zero(p, pageSize);
if( pN ) *pN = pageSize;
return p;
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
633 634 635 636 637 638 639 640 641 642 643 644 645 646 |
nrid = content_put_ex(pWiki, 0, 0, 0, 1);
moderation_table_create();
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
}
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
manifest_crosslink(nrid, pWiki, MC_NONE);
return nrid;
}
/*
** Output a selection box from which the user can select the
** wiki mimetype.
*/
| > > > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
nrid = content_put_ex(pWiki, 0, 0, 0, 1);
moderation_table_create();
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
}
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
manifest_crosslink(nrid, pWiki, MC_NONE);
if( login_is_individual() ){
alert_user_contact(login_name());
}
return nrid;
}
/*
** Output a selection box from which the user can select the
** wiki mimetype.
*/
|
| ︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
Stmt q = empty_Stmt;
int n = 0;
db_begin_transaction();
db_prepare(&q, "SELECT"
" substr(tagname,6) AS name"
" FROM tag JOIN tagxref USING('tagid')"
" WHERE tagname GLOB 'wiki-*'"
" UNION SELECT 'Sandbox' AS name"
" ORDER BY name COLLATE NOCASE");
CX("[");
while( SQLITE_ROW==db_step(&q) ){
char const * zName = db_column_text(&q,0);
if(n++){
CX(",");
| > > | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 |
Stmt q = empty_Stmt;
int n = 0;
db_begin_transaction();
db_prepare(&q, "SELECT"
" substr(tagname,6) AS name"
" FROM tag JOIN tagxref USING('tagid')"
" WHERE tagname GLOB 'wiki-*'"
" AND TYPEOF(tagxref.value+0)='integer'"
/* ^^^ elide wiki- tags which are not wiki pages */
" UNION SELECT 'Sandbox' AS name"
" ORDER BY name COLLATE NOCASE");
CX("[");
while( SQLITE_ROW==db_step(&q) ){
char const * zName = db_column_text(&q,0);
if(n++){
CX(",");
|
| ︙ | ︙ | |||
1197 1198 1199 1200 1201 1202 1203 |
"data-tab-label='Editor' "
"class='hidden'"
">");
CX("<div class='"
"wikiedit-options flex-container flex-row child-gap-small'>");
CX("<div class='input-with-label'>"
"<label>Mime type</label>");
| | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 |
"data-tab-label='Editor' "
"class='hidden'"
">");
CX("<div class='"
"wikiedit-options flex-container flex-row child-gap-small'>");
CX("<div class='input-with-label'>"
"<label>Mime type</label>");
mimetype_option_menu("text/x-markdown");
CX("</div>");
style_select_list_int("select-font-size",
"editor_font_size", "Editor font size",
NULL/*tooltip*/,
100,
"100%", 100, "125%", 125,
"150%", 150, "175%", 175,
|
| ︙ | ︙ | |||
1394 1395 1396 1397 1398 1399 1400 |
wiki_standard_submenu(W_ALL_BUT(W_NEW));
@ <p>Rules for wiki page names:</p>
well_formed_wiki_name_rules();
form_begin(0, "%R/wikinew");
@ <p>Name of new wiki page:
@ <input style="width: 35;" type="text" name="name" value="%h(zName)" /><br />
@ %z(href("%R/markup_help"))Markup style</a>:
| | | 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 |
wiki_standard_submenu(W_ALL_BUT(W_NEW));
@ <p>Rules for wiki page names:</p>
well_formed_wiki_name_rules();
form_begin(0, "%R/wikinew");
@ <p>Name of new wiki page:
@ <input style="width: 35;" type="text" name="name" value="%h(zName)" /><br />
@ %z(href("%R/markup_help"))Markup style</a>:
mimetype_option_menu("text/x-markdown");
@ <br /><input type="submit" value="Create" />
@ </p></form>
if( zName[0] ){
@ <p><span class="wikiError">
@ "%h(zName)" is not a valid wiki page name!</span></p>
}
style_finish_page();
|
| ︙ | ︙ | |||
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 | @ count(*) AS wcnt @ FROM @ tag, @ tagxref @ WHERE @ tag.tagname GLOB 'wiki-*' @ AND tagxref.tagid=tag.tagid @ GROUP BY 1 @ ORDER BY 2; ; /* ** WEBPAGE: wcontent ** | > | 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | @ count(*) AS wcnt @ FROM @ tag, @ tagxref @ WHERE @ tag.tagname GLOB 'wiki-*' @ AND tagxref.tagid=tag.tagid @ AND TYPEOF(wrid)='integer' -- only wiki- tags which are wiki pages @ GROUP BY 1 @ ORDER BY 2; ; /* ** WEBPAGE: wcontent ** |
| ︙ | ︙ |
Changes to src/winfile.c.
| ︙ | ︙ | |||
280 281 282 283 284 285 286 |
** characters are converted to '/'.
*/
void win32_getcwd(char *zBuf, int nBuf){
int i;
char *zUtf8;
wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
| | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
** characters are converted to '/'.
*/
void win32_getcwd(char *zBuf, int nBuf){
int i;
char *zUtf8;
wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf );
if( GetCurrentDirectoryW(nBuf, zWide)==0 ){
fossil_fatal("cannot find current working directory.");
}
zUtf8 = fossil_path_to_utf8(zWide);
fossil_free(zWide);
for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/';
strncpy(zBuf, zUtf8, nBuf);
fossil_path_free(zUtf8);
}
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
286 287 288 289 290 291 292 |
** Issue a fatal error.
*/
static NORETURN void winhttp_fatal(
const char *zOp,
const char *zService,
const char *zErr
){
| | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
** Issue a fatal error.
*/
static NORETURN void winhttp_fatal(
const char *zOp,
const char *zService,
const char *zErr
){
fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr);
}
/*
** Make sure the server stops as soon as possible after the stopper file
** is found. If there is no stopper file name, do nothing.
*/
static void win32_server_stopper(void *pAppData){
|
| ︙ | ︙ | |||
602 603 604 605 606 607 608 609 |
iPort++;
continue;
}
}
break;
}
if( iPort>mxPort ){
if( mnPort==mxPort ){
| > | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
iPort++;
continue;
}
}
break;
}
if( iPort>mxPort ){
/* These exits are merely fatal because firewall settings can cause them. */
if( mnPort==mxPort ){
fossil_fatal("unable to open listening socket on port %d", mnPort);
}else{
fossil_fatal("unable to open listening socket on any"
" port in the range %d..%d", mnPort, mxPort);
}
}
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
fossil_panic("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d",
|
| ︙ | ︙ | |||
906 907 908 909 910 911 912 |
if( GetStdHandle(STD_INPUT_HANDLE)!=NULL ){ return 1; }
/* Try to start the control dispatcher thread for the service. */
if( !StartServiceCtrlDispatcherW(ServiceTable) ){
if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
return 1;
}else{
| | | 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
if( GetStdHandle(STD_INPUT_HANDLE)!=NULL ){ return 1; }
/* Try to start the control dispatcher thread for the service. */
if( !StartServiceCtrlDispatcherW(ServiceTable) ){
if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){
return 1;
}else{
fossil_fatal("error from StartServiceCtrlDispatcher()");
}
}
return 0;
}
/* Duplicate #ifdef needed for mkindex */
#ifdef _WIN32
|
| ︙ | ︙ |
Changes to test/commit-warning.test.
| ︙ | ︙ | |||
170 171 172 173 174 175 176 |
# of source files that MUST NEVER BE TEXT.
#
test_block_in_checkout pre-commit-warnings-fossil-1 {
fossil test-commit-warning --no-settings
} {
test pre-commit-warnings-fossil-1 {[normalize_result] eq \
[subst -nocommands -novariables [string trim {
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | < < | | | | | | | | | | | | | | | | > > > > | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# of source files that MUST NEVER BE TEXT.
#
test_block_in_checkout pre-commit-warnings-fossil-1 {
fossil test-commit-warning --no-settings
} {
test pre-commit-warnings-fossil-1 {[normalize_result] eq \
[subst -nocommands -novariables [string trim {
1\tart/branching.odp\tbinary data
1\tart/concept1.dia\tbinary data
1\tart/concept2.dia\tbinary data
1\tcompat/zlib/contrib/blast/test.pk\tbinary data
1\tcompat/zlib/contrib/dotzlib/DotZLib.build\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/DotZLib.chm\tbinary data
1\tcompat/zlib/contrib/dotzlib/DotZLib.sln\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/CodecBase.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/Deflater.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/DotZLib.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/DotZLib/GZipStream.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/Inflater.cs\tinvalid UTF-8
1\tcompat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/LICENSE_1_0.txt\tCR/LF line endings
1\tcompat/zlib/contrib/dotzlib/readme.txt\tCR/LF line endings
1\tcompat/zlib/contrib/gcc_gvmat64/gvmat64.S\tCR/LF line endings
1\tcompat/zlib/contrib/masmx64/bld_ml64.bat\tCR/LF line endings
1\tcompat/zlib/contrib/masmx64/gvmat64.asm\tCR/LF line endings
1\tcompat/zlib/contrib/masmx64/inffas8664.c\tCR/LF line endings
1\tcompat/zlib/contrib/masmx64/inffasx64.asm\tCR/LF line endings
1\tcompat/zlib/contrib/masmx64/readme.txt\tCR/LF line endings
1\tcompat/zlib/contrib/masmx86/bld_ml32.bat\tCR/LF line endings
1\tcompat/zlib/contrib/masmx86/inffas32.asm\tCR/LF line endings
1\tcompat/zlib/contrib/masmx86/match686.asm\tCR/LF line endings
1\tcompat/zlib/contrib/masmx86/readme.txt\tCR/LF line endings
1\tcompat/zlib/contrib/puff/zeros.raw\tbinary data
1\tcompat/zlib/contrib/testzlib/testzlib.c\tCR/LF line endings
1\tcompat/zlib/contrib/testzlib/testzlib.txt\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/readme.txt\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/miniunz.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/minizip.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/testzlib.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlib.rc\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibvc.def\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibvc.sln\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/miniunz.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/minizip.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/testzlib.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/zlib.rc\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/zlibvc.def\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/zlibvc.sln\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc11/zlibvc.vcxproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc12/zlibvc.def\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc14/zlibvc.def\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/miniunz.vcproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/minizip.vcproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/testzlib.vcproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/testzlibdll.vcproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/zlib.rc\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/zlibstat.vcproj\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/zlibvc.def\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/zlibvc.sln\tCR/LF line endings
1\tcompat/zlib/contrib/vstudio/vc9/zlibvc.vcproj\tCR/LF line endings
1\tcompat/zlib/win32/zlib.def\tCR/LF line endings
1\tcompat/zlib/zlib.3.pdf\tbinary data
1\tcompat/zlib/zlib.map\tCR/LF line endings
1\tskins/blitz/arrow_project.png\tbinary data
1\tskins/blitz/dir.png\tbinary data
1\tskins/blitz/file.png\tbinary data
1\tskins/blitz/fossil_100.png\tbinary data
1\tskins/blitz/fossil_80_reversed_darkcyan.png\tbinary data
1\tskins/blitz/fossil_80_reversed_darkcyan_text.png\tbinary data
1\tskins/blitz/rss_20.png\tbinary data
1\tskins/bootstrap/css.txt\tlong lines
1\tsrc/alerts/bflat2.wav\tbinary data
1\tsrc/alerts/bflat3.wav\tbinary data
1\tsrc/alerts/bloop.wav\tbinary data
1\tsrc/alerts/plunk.wav\tbinary data
1\tsrc/sounds/0.wav\tbinary data
1\tsrc/sounds/1.wav\tbinary data
1\tsrc/sounds/2.wav\tbinary data
1\tsrc/sounds/3.wav\tbinary data
1\tsrc/sounds/4.wav\tbinary data
1\tsrc/sounds/5.wav\tbinary data
1\tsrc/sounds/6.wav\tbinary data
1\tsrc/sounds/7.wav\tbinary data
1\tsrc/sounds/8.wav\tbinary data
1\tsrc/sounds/9.wav\tbinary data
1\tsrc/sounds/a.wav\tbinary data
1\tsrc/sounds/b.wav\tbinary data
1\tsrc/sounds/c.wav\tbinary data
1\tsrc/sounds/d.wav\tbinary data
1\tsrc/sounds/e.wav\tbinary data
1\tsrc/sounds/f.wav\tbinary data
1\ttest/th1-docs-input.txt\tCR/LF line endings
1\ttest/th1-hooks-input.txt\tCR/LF line endings
1\ttest/utf16be.txt\tUnicode
1\ttest/utf16le.txt\tUnicode
1\twin/buildmsvc.bat\tCR/LF line endings
1\twin/fossil.ico\tbinary data
1\twin/fossil.rc\tinvalid UTF-8
1\twww/apple-touch-icon.png\tbinary data
1\twww/background.jpg\tbinary data
1\twww/build-icons/linux.gif\tbinary data
1\twww/build-icons/linux64.gif\tbinary data
1\twww/build-icons/mac.gif\tbinary data
1\twww/build-icons/openbsd.gif\tbinary data
1\twww/build-icons/src.gif\tbinary data
1\twww/build-icons/win32.gif\tbinary data
1\twww/copyright-release.pdf\tbinary data
1\twww/encode1.gif\tbinary data
1\twww/encode2.gif\tbinary data
1\twww/encode3.gif\tbinary data
1\twww/encode4.gif\tbinary data
1\twww/encode5.gif\tbinary data
1\twww/encode6.gif\tbinary data
1\twww/encode7.gif\tbinary data
1\twww/encode8.gif\tbinary data
1\twww/encode9.gif\tbinary data
1\twww/fossil.gif\tbinary data
1\twww/fossil2.gif\tbinary data
1\twww/fossil3.gif\tbinary data
1\twww/fossil_logo_small.gif\tbinary data
1\twww/fossil_logo_small2.gif\tbinary data
1\twww/fossil_logo_small3.gif\tbinary data
1\twww/server/windows/cgi-bin-perm.png\tbinary data
1\twww/server/windows/cgi-exec-perm.png\tbinary data
1\twww/server/windows/cgi-install-iis.png\tbinary data
1\twww/server/windows/cgi-script-map.png\tbinary data
1\twww/xkcd-git.gif\tbinary data
1}]]}
}
###############################################################################
test_cleanup
|
Changes to test/json.test.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 |
# We need a JSON parser to effectively test the JSON produced by
# fossil. It looks like the one from tcllib is exactly what we need.
# On ActiveTcl, add it with teacup. On other platforms, YMMV.
# teacup install json
# teacup install json::write
if {[catch {package require json}] != 0} then {
| > | > > | | 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 |
# We need a JSON parser to effectively test the JSON produced by
# fossil. It looks like the one from tcllib is exactly what we need.
# On ActiveTcl, add it with teacup. On other platforms, YMMV.
# teacup install json
# teacup install json::write
if {[catch {package require json}] != 0} then {
puts {
The "json" package for Tcl is not available.
Please see: https://core.tcl-lang.org/tcllib
}
test_cleanup_then_return
}
proc json2dict {txt} {
set rc [catch {::json::json2dict $txt} result options]
if {$rc != 0} {
protOut "JSON ERROR: $result"
return {}
}
return $result
}
# and that the json itself smells ok and has the expected API error code in it
fossil json -expectError
set JR [json2dict $RESULT]
if {$JR eq ""} {
puts "Fossil was not compiled with JSON support (bad JSON)."
test_cleanup_then_return
}
test json-1 {[dict exists $JR resultCode]
&& [dict get $JR resultCode] in "FOSSIL-3002 FOSSIL-4102"}
# Use the CLI interface to execute a JSON command. Sets the global
# RESULT to the response text, and JR to a Tcl dict conversion of the
# response body.
#
# Returns "200" or "500".
proc fossil_json {args} {
|
| ︙ | ︙ |
Changes to test/merge_renames.test.
| ︙ | ︙ | |||
521 522 523 524 525 526 527 |
write_file f1 "line1\nline3\nline4"
fossil commit -m "edit f1 on b" --tag c10
fossil update m1
fossil merge b
test_status_list merge_renames-13-6 $RESULT {
UPDATE f1
| < < < < < < | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 |
write_file f1 "line1\nline3\nline4"
fossil commit -m "edit f1 on b" --tag c10
fossil update m1
fossil merge b
test_status_list merge_renames-13-6 $RESULT {
UPDATE f1
}
test_file_contents merge_renames-13-7 f2n "line1"
fossil revert
test_status_list merge_renames-13-8 $RESULT {
REVERT f1
}
fossil update trunk
fossil merge --integrate b
test_status_list merge_renames-13-9 $RESULT {
UPDATE f1
}
test_file_contents merge_renames-13-10 f2n "line1"
fossil revert
test_status_list merge_renames-13-11 $RESULT {
REVERT f1
}
######################################
#
# Tests for troubles not specifically linked with renames but that I'd like to
# write:
# [c26c63eb1b] - 'merge --backout' does not handle conflicts properly
|
| ︙ | ︙ |
Added test/merge_renames_2.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#
# Tests for merging with renames
#
#
proc commit_id {version} {
regexp -line {^artifact:\s+(\S+)} [fossil whatis $version] - id
return $id
}
require_no_open_checkout
#################################################################
# Test 1 #
# https://fossil-scm.org/forum/forumpost/549700437b #
#################################################################
test_setup
write_file file1 "file1\n"
fossil add file1
fossil commit -m "added file1"
write_file file2 "file2\n"
fossil add file2
fossil commit -m "added file2" --branch added
write_file file2 "edit file2 on added\n"
fossil commit -m "edited file2"
fossil mv --hard file2 file2.renamed
fossil commit -m "renamed file2" --branch renamed
fossil branch new branched current
write_file file2.renamed "edit file2.renamed on renamed\n"
fossil commit -m "edited file2.renamed"
fossil update trunk
fossil merge renamed
fossil commit -m "merged from renamed"
write_file file2.renamed "edit file2.renamed on trunk (1)\n"
fossil commit -m "edited file2.renamed on trunk (1)"
fossil update branched
fossil merge trunk
test_status_list merge_renames_2-1.1 $RESULT {UPDATE file2.renamed}
fossil commit -m "merged edit from trunk (1:this merge succeeded)"
fossil update trunk
write_file file2.renamed "edit2 file2.renamed on trunk (2)\n"
fossil commit -m "edited file2.renamed on trunk (2)"
fossil update branched
fossil merge trunk
test_status_list merge_renames_2-1.2 $RESULT {UPDATE file2.renamed}
test_cleanup
|
Changes to test/release-checklist.wiki.
| ︙ | ︙ | |||
73 74 75 76 77 78 79 | <li> <b>fossil sync</b> <li> <b>fossil test-integrity</b> </ol> <li><p> Run the following commands on Linux and verify no major memory leaks and no run-time errors or warnings (except for the well-known jump on an | | > > > > | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | <li> <b>fossil sync</b> <li> <b>fossil test-integrity</b> </ol> <li><p> Run the following commands on Linux and verify no major memory leaks and no run-time errors or warnings (except for the well-known jump on an uninitialized value that occurs within zlib).</p> <ol type="a"> <li> <b>valgrind fossil rebuild</b> <li> <b>valgrind fossil sync</b> </ol> <p>Achtung: make sure to point valgrind to the proper fossil binary so that it does not pick up another from the PATH.</p> <li><p> Inspect [http://fossil-scm.org/home/vdiff?from=release&to=trunk&sbs=1|all code changes since the previous release], paying particular attention to the following details: <ol type="a"> <li> Can a malicious HTTP request cause a buffer overrun. |
| ︙ | ︙ |
Changes to test/symlinks.test.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 | ############################################################################ # # Symbolic link tests. # set path [file dirname [info script]] | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
############################################################################
#
# Symbolic link tests.
#
set path [file dirname [info script]]
if {$is_windows} {
puts "Symlinks are not supported on Windows."
test_cleanup_then_return
}
fossil test-th-eval --open-config "setting allow-symlinks"
if {![string is true -strict [normalize_result]]} {
|
| ︙ | ︙ |
Changes to test/th1.test.
| ︙ | ︙ | |||
729 730 731 732 733 734 735 736 |
fossil test-th-eval "trace {}"
test th1-trace-1 {$RESULT eq {}}
###############################################################################
fossil test-th-eval --th-trace "trace {}"
if {$th1Hooks} {
| > > > > > | | > > > > > | | | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 |
fossil test-th-eval "trace {}"
test th1-trace-1 {$RESULT eq {}}
###############################################################################
fossil test-th-eval --th-trace "trace {}"
set normalized_result [normalize_result]
regsub -- {\n/\*\*\*\*\* Subprocess \d+ exit\(\d+\) \*\*\*\*\*/} \
$normalized_result {} normalized_result
if {$th1Hooks} {
test th1-trace-2 {$normalized_result eq \
{------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
------------------- END TRACE LOG -------------------}}
} else {
test th1-trace-2 {$normalized_result eq \
{------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
th1-setup {} => TH_OK<br />
------------------- END TRACE LOG -------------------}}
}
###############################################################################
fossil test-th-eval "trace {this is a trace message.}"
test th1-trace-3 {$RESULT eq {}}
###############################################################################
fossil test-th-eval --th-trace "trace {this is a trace message.}"
set normalized_result [normalize_result]
regsub -- {\n/\*\*\*\*\* Subprocess \d+ exit\(\d+\) \*\*\*\*\*/} \
$normalized_result {} normalized_result
if {$th1Hooks} {
test th1-trace-4 {$normalized_result eq \
{------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
this is a trace message.
------------------- END TRACE LOG -------------------}}
} else {
test th1-trace-4 {$normalized_result eq \
{------------------ BEGIN TRACE LOG ------------------
th1-init 0x0 => 0x0<br />
th1-setup {} => TH_OK<br />
this is a trace message.
------------------- END TRACE LOG -------------------}}
}
|
| ︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 |
###############################################################################
fossil test-th-eval "globalState vfs"
test th1-globalState-14 {[string length $RESULT] == 0}
###############################################################################
| | | 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 |
###############################################################################
fossil test-th-eval "globalState vfs"
test th1-globalState-14 {[string length $RESULT] == 0}
###############################################################################
if {$is_windows} {
set altVfs win32-longpath
} else {
set altVfs unix-dotfile
}
###############################################################################
|
| ︙ | ︙ |
Changes to win/Makefile.mingw.
| ︙ | ︙ | |||
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ $(SRCDIR)/graph.js \ | > > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ $(SRCDIR)/graph.js \ |
| ︙ | ︙ |
Changes to win/Makefile.mingw.mistachkin.
| ︙ | ︙ | |||
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ $(SRCDIR)/graph.js \ | > > | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | $(SRCDIR)/fossil.bootstrap.js \ $(SRCDIR)/fossil.confirmer.js \ $(SRCDIR)/fossil.copybutton.js \ $(SRCDIR)/fossil.dom.js \ $(SRCDIR)/fossil.fetch.js \ $(SRCDIR)/fossil.info-diff.js \ $(SRCDIR)/fossil.numbered-lines.js \ $(SRCDIR)/fossil.page.brlist.js \ $(SRCDIR)/fossil.page.fileedit.js \ $(SRCDIR)/fossil.page.forumpost.js \ $(SRCDIR)/fossil.page.pikchrshow.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.js \ $(SRCDIR)/fossil.popupwidget.js \ $(SRCDIR)/fossil.storage.js \ $(SRCDIR)/fossil.tabs.js \ $(SRCDIR)/fossil.wikiedit-wysiwyg.js \ $(SRCDIR)/graph.js \ |
| ︙ | ︙ |
Changes to win/Makefile.msc.
| ︙ | ︙ | |||
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
"$(SRCDIR)\fossil.bootstrap.js" \
"$(SRCDIR)\fossil.confirmer.js" \
"$(SRCDIR)\fossil.copybutton.js" \
"$(SRCDIR)\fossil.dom.js" \
"$(SRCDIR)\fossil.fetch.js" \
"$(SRCDIR)\fossil.info-diff.js" \
"$(SRCDIR)\fossil.numbered-lines.js" \
"$(SRCDIR)\fossil.page.fileedit.js" \
"$(SRCDIR)\fossil.page.forumpost.js" \
"$(SRCDIR)\fossil.page.pikchrshow.js" \
"$(SRCDIR)\fossil.page.wikiedit.js" \
"$(SRCDIR)\fossil.pikchr.js" \
"$(SRCDIR)\fossil.popupwidget.js" \
"$(SRCDIR)\fossil.storage.js" \
"$(SRCDIR)\fossil.tabs.js" \
"$(SRCDIR)\fossil.wikiedit-wysiwyg.js" \
"$(SRCDIR)\graph.js" \
| > > | 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 |
"$(SRCDIR)\fossil.bootstrap.js" \
"$(SRCDIR)\fossil.confirmer.js" \
"$(SRCDIR)\fossil.copybutton.js" \
"$(SRCDIR)\fossil.dom.js" \
"$(SRCDIR)\fossil.fetch.js" \
"$(SRCDIR)\fossil.info-diff.js" \
"$(SRCDIR)\fossil.numbered-lines.js" \
"$(SRCDIR)\fossil.page.brlist.js" \
"$(SRCDIR)\fossil.page.fileedit.js" \
"$(SRCDIR)\fossil.page.forumpost.js" \
"$(SRCDIR)\fossil.page.pikchrshow.js" \
"$(SRCDIR)\fossil.page.whistory.js" \
"$(SRCDIR)\fossil.page.wikiedit.js" \
"$(SRCDIR)\fossil.pikchr.js" \
"$(SRCDIR)\fossil.popupwidget.js" \
"$(SRCDIR)\fossil.storage.js" \
"$(SRCDIR)\fossil.tabs.js" \
"$(SRCDIR)\fossil.wikiedit-wysiwyg.js" \
"$(SRCDIR)\graph.js" \
|
| ︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | echo "$(SRCDIR)\fossil.bootstrap.js" >> $@ echo "$(SRCDIR)\fossil.confirmer.js" >> $@ echo "$(SRCDIR)\fossil.copybutton.js" >> $@ echo "$(SRCDIR)\fossil.dom.js" >> $@ echo "$(SRCDIR)\fossil.fetch.js" >> $@ echo "$(SRCDIR)\fossil.info-diff.js" >> $@ echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@ echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@ echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@ echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@ echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@ echo "$(SRCDIR)\fossil.pikchr.js" >> $@ echo "$(SRCDIR)\fossil.popupwidget.js" >> $@ echo "$(SRCDIR)\fossil.storage.js" >> $@ echo "$(SRCDIR)\fossil.tabs.js" >> $@ echo "$(SRCDIR)\fossil.wikiedit-wysiwyg.js" >> $@ echo "$(SRCDIR)\graph.js" >> $@ | > > | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 | echo "$(SRCDIR)\fossil.bootstrap.js" >> $@ echo "$(SRCDIR)\fossil.confirmer.js" >> $@ echo "$(SRCDIR)\fossil.copybutton.js" >> $@ echo "$(SRCDIR)\fossil.dom.js" >> $@ echo "$(SRCDIR)\fossil.fetch.js" >> $@ echo "$(SRCDIR)\fossil.info-diff.js" >> $@ echo "$(SRCDIR)\fossil.numbered-lines.js" >> $@ echo "$(SRCDIR)\fossil.page.brlist.js" >> $@ echo "$(SRCDIR)\fossil.page.fileedit.js" >> $@ echo "$(SRCDIR)\fossil.page.forumpost.js" >> $@ echo "$(SRCDIR)\fossil.page.pikchrshow.js" >> $@ echo "$(SRCDIR)\fossil.page.whistory.js" >> $@ echo "$(SRCDIR)\fossil.page.wikiedit.js" >> $@ echo "$(SRCDIR)\fossil.pikchr.js" >> $@ echo "$(SRCDIR)\fossil.popupwidget.js" >> $@ echo "$(SRCDIR)\fossil.storage.js" >> $@ echo "$(SRCDIR)\fossil.tabs.js" >> $@ echo "$(SRCDIR)\fossil.wikiedit-wysiwyg.js" >> $@ echo "$(SRCDIR)\graph.js" >> $@ |
| ︙ | ︙ |
Changes to www/alerts.md.
| ︙ | ︙ | |||
549 550 551 552 553 554 555 556 557 558 559 560 561 562 | * The [`test-add-alerts`](/help?cmd=test-add-alerts) command Web pages available to users and subscribers: * The [`/subscribe`](/help?cmd=/subscribe) page * The [`/alerts`](/help?cmd=/alerts) page * The [`/unsubscribe`](/help?cmd=/unsubscribe) page * The [`/contact_admin`](/help?cmd=/contact_admin) page Administrator-only web pages: * The [`/setup_notification`](/help?cmd=/setup_notification) page * The [`/subscribers`](/help?cmd=/subscribers) page | > | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | * The [`test-add-alerts`](/help?cmd=test-add-alerts) command Web pages available to users and subscribers: * The [`/subscribe`](/help?cmd=/subscribe) page * The [`/alerts`](/help?cmd=/alerts) page * The [`/unsubscribe`](/help?cmd=/unsubscribe) page * The [`/renew`](/help?cmd=/renew) page * The [`/contact_admin`](/help?cmd=/contact_admin) page Administrator-only web pages: * The [`/setup_notification`](/help?cmd=/setup_notification) page * The [`/subscribers`](/help?cmd=/subscribers) page |
| ︙ | ︙ | |||
572 573 574 575 576 577 578 | above sufficed for your purposes, feel free to skip this section, which runs to the end of this document. <a id="datades"></a> ### Data Design | | | 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 |
above sufficed for your purposes, feel free to skip this section, which
runs to the end of this document.
<a id="datades"></a>
### Data Design
There are two new tables in the repository database, starting with
Fossil 2.7. These tables are not created in new repositories by
default. The tables only come into existence as needed when email
alerts are configured and used.
* <b>SUBSCRIBER</b> →
The subscriber table records the email address for people who
|
| ︙ | ︙ | |||
597 598 599 600 601 602 603 |
A pending\_alert always refers to an entry in the
EVENT table. The EVENT table is part of the standard schema
and records timeline entries. In other words, there is one
row in the EVENT table for each possible timeline entry. The
PENDING\_ALERT table refers to EVENT table entries for which
we might need to send alert emails.
| | | | | < | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 |
A pending\_alert always refers to an entry in the
EVENT table. The EVENT table is part of the standard schema
and records timeline entries. In other words, there is one
row in the EVENT table for each possible timeline entry. The
PENDING\_ALERT table refers to EVENT table entries for which
we might need to send alert emails.
There was a third table "EMAIL_BOUNCE" in Fossil versions 2.7 through 2.14.
That table was intended to record email bounce history so that
subscribers with excessive bounces can be turned off. But that feature
was never implemented and the table was removed in Fossil 2.15.
As pointed out above, ["subscribers" are distinct from "users"](#uvs).
The SUBSCRIBER.SUNAME field is the optional linkage between users and
subscribers.
<a id="stdout"></a>
|
| ︙ | ︙ |
Changes to www/build.wiki.
| ︙ | ︙ | |||
248 249 250 251 252 253 254 | These instructions assume that docker is installed and that the user running these instructions has permission to do so (i.e., they are <tt>root</tt> or are a member of the <tt>docker</tt> group). First, create a file named <tt>Dockerfile</tt> with the following contents: <pre><code> | > > | > < < < < < | 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 |
These instructions assume that docker is installed and that the user running
these instructions has permission to do so (i.e., they are <tt>root</tt> or
are a member of the <tt>docker</tt> group).
First, create a file named <tt>Dockerfile</tt> with the following contents:
<pre><code>
# Alpine >3.13 breaks stuff on many host OSes! For details see:
# https://wiki.alpinelinux.org/wiki/Draft_Release_Notes_for_Alpine_3.14.0#faccessat2
# FROM alpine:edge
FROM alpine:3.13
RUN apk update \
&& apk upgrade \
&& apk add --no-cache \
curl gcc make tcl \
musl-dev \
openssl-dev zlib-dev \
openssl-libs-static zlib-static \
&& curl \
"https://fossil-scm.org/home/tarball/fossil-src.tar.gz?name=fossil-src&uuid=trunk" \
-o fossil-src.tar.gz \
&& tar xf fossil-src.tar.gz \
&& cd fossil-src \
&& ./configure \
--static \
--disable-fusefs \
--with-th1-docs \
--with-th1-hooks \
&& make
</code></pre>
Be sure to modify the <tt>configure</tt> flags, if desired. e.g., add <tt>--json</tt>
for JSON support.
From the directory containing that file, build it with docker:
|
| ︙ | ︙ |
Changes to www/caps/admin-v-setup.md.
| ︙ | ︙ | |||
255 256 257 258 259 260 261 | Setup users get [every user capability](./ref.html) of Fossil except for [two exceptionally dangerous capabilities](#dcap), which they can later grant to themselves or to others. In addition, Setup users can use every feature of the Fossil UI. If Fossil can do a thing, a Setup user on that repo can make Fossil do it. | | > < | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
Setup users get [every user capability](./ref.html) of Fossil except for
[two exceptionally dangerous capabilities](#dcap), which they can later
grant to themselves or to others.
In addition, Setup users can use every feature of the Fossil UI. If Fossil can do a
thing, a Setup user on that repo can make Fossil do it.
Setup users can do many things that Admin users cannot. They may not
only use all of the Admin UI features, they may also:
* See record IDs (RIDs) on screens that show them
* See the MIME type of attachments on [`/ainfo` pages](/help?cmd=/ainfo)
* See a remote repo’s HTTP [cache status](/help?cmd=/cachestat)
and [pull cache entries](/help?cmd=/cacheget)
* Edit a Setup user’s account!
The “Admin” feature of Fossil UI is so-named because Admin users can use
|
| ︙ | ︙ |
Changes to www/caps/index.md.
| ︙ | ︙ | |||
319 320 321 322 323 324 325 |
those changes to that repository. Presumably Fossil does this
instead of using a pipe to ease portability to Windows.
Checks for capabilities like [**Read**][o] and [**Write**][i] within the
HTTP conversation between two Fossil instances only have a useful effect
when done over an `http[s]://` URL.
| | | 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
those changes to that repository. Presumably Fossil does this
instead of using a pipe to ease portability to Windows.
Checks for capabilities like [**Read**][o] and [**Write**][i] within the
HTTP conversation between two Fossil instances only have a useful effect
when done over an `http[s]://` URL.
[sxcap]: /file?ci=8813ae91a699ac73&name=src/main.c&ln=2632-2637
## <a name="pubpg"></a>Public Pages
In Admin → Access, there is an option for giving a list of [globs][glob]
to name URLs which get treated as if the visitor had [the default cap
set](#defcap). For example, you could take the [**Read**][o] capability
|
| ︙ | ︙ |
Changes to www/changes.wiki.
1 2 3 | <title>Change Log</title> <a name='v2_15'></a> | > > > > > > > > > > > > > > > > > > > | > > | 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 |
<title>Change Log</title>
<a name='v2_16'></a>
<h2>Changes for Version 2.16 (pending)</h2>
* The [/brlist|/brlist web page] allows the user to
select multiple branches to be displayed together in a single
timeline.
* The [./forum.wiki|Forum] provides a hyperlink on the author of each
post that goes to a timeline of recent posts by that same author.
* The [/help?cmd=merge|fossil merge] command now does a better job merging
branches where files have been renamed between the current branch and the
branch being merged.
* The [/help?cmd=open|fossil open] command allows the repository file
to be inside the working directory without requiring the --force flag.
* The [/help?cmd=/wikiedit|/wikiedit] and [/help?cmd=/wikinew|/wikinew]
pages now default to markdown format.
* The [/help?cmd=/login|/login] page now links to a user's forum post
timeline if the repository has forum posts.
* Tags may now be propagated for forum posts, wiki pages, and technotes.
The [/help?cmd=tag|tag command] can now manipulate and list such tags.
<a name='v2_15'></a>
<h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07)</h2>
* <b>Patch 2.15.1:</b> Fix a data exfiltration bug in the server. <b>Upgrading to
the patch is recommended.</b><p>
* The [./defcsp.md|default CSP] has been relaxed slightly to allow
images to be loaded from any URL. All other resources are still
locked down by default.
* The built-in skins all use the "[/help?cmd=mainmenu|mainmenu]"
setting to determine the content of the main menu.
The ability to edit the
"mainmenu" setting is added on the /Admin/Configuration page.
|
| ︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 |
* Update the built-in SQLite to version 3.35.0.
* The ./configure script now has the --print-minimum-sqlite-version option
that prints the minimum SQLite version required by the current version
of Fossil. This might be used by integrators who insist on building
Fossil to link against the system SQLite library rather than the
built-in copy of SQLite, to verify that their system SQLite library
is recent enough.
<a name='v2_14'></a>
| > > > > > | | > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
* Update the built-in SQLite to version 3.35.0.
* The ./configure script now has the --print-minimum-sqlite-version option
that prints the minimum SQLite version required by the current version
of Fossil. This might be used by integrators who insist on building
Fossil to link against the system SQLite library rather than the
built-in copy of SQLite, to verify that their system SQLite library
is recent enough.
* Webpage that shows [/help?cmd=/whistory|history of a wiki page]
gained client-side UI to help with comparison between two arbitrary
versions of a wiki (by the means of anchoring a "baseline" version)
and the ability to squeeze several sequential edits made by the same
user into a single "recycled" row (the latest edit in that sequence).
<a name='v2_14'></a>
<h2>Changes for Version 2.14 (2021-01-20) and Patch 2.14.1 on (2021-04-07)</h2>
* <b>Patch 2.14.1:</b> Fix a data exfiltration bug in the server.
<b>Upgrading to the patch is recommended.</b><p>
* <b>Schema Update Notice #1:</b>
This release drops a trigger from the database schema (replacing
it with a TEMP trigger that is created as needed). This
change happens automatically the first time you
add content to a repository using Fossil 2.14 or later. No
action is needed on your part. However, if you upgrade to
version 2.14 and then later downgrade or otherwise use an earlier
|
| ︙ | ︙ |
Changes to www/fossil-v-git.wiki.
| ︙ | ︙ | |||
541 542 543 544 545 546 547 | software configuration management problems or D. Richard Hipp scale problems when choosing your DVCS. An [https://en.wikipedia.org/wiki/Impact_wrench|automotive air impact wrench] running at 8000 RPM driving an M8 socket-cap bolt at 16 cm/s is not the best way to hang a picture on the living room wall. | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | software configuration management problems or D. Richard Hipp scale problems when choosing your DVCS. An [https://en.wikipedia.org/wiki/Impact_wrench|automotive air impact wrench] running at 8000 RPM driving an M8 socket-cap bolt at 16 cm/s is not the best way to hang a picture on the living room wall. <h4 id="branches">2.5.3 Individual Branches vs. The Entire Change History</h4> Both Fossil and Git store history as a directed acyclic graph (DAG) of changes, but Git tends to focus more on individual branches of the DAG, whereas Fossil puts more emphasis on the entire DAG. For example, the default behavior in Git is to only synchronize a single branch, whereas with Fossil the only sync option is to |
| ︙ | ︙ |
Changes to www/javascript.md.
| ︙ | ︙ | |||
568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
SELECT xfrom, xmsg FROM chat WHERE msgid > 1234;
…would pull the messages submitted since the last poll. Making the
gateway bidirectional should be possible as well, as long as it properly
uses SQLite transactions.
----
## <a id="future"></a>Future Plans for JavaScript in Fossil
As of mid-2020, the informal provisional plan is to increase Fossil
UI's use of JavaScript considerably compared to its historically minimal
uses. To that end, a framework of Fossil-centric APIs is being developed
| > > > > > > > > > > > > > | 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 |
SELECT xfrom, xmsg FROM chat WHERE msgid > 1234;
…would pull the messages submitted since the last poll. Making the
gateway bidirectional should be possible as well, as long as it properly
uses SQLite transactions.
### <a id="brlist"></a>List of branches
Since Fossil 2.16 [`/brlist`](/brlist) page uses JavaScript to enable
selection of several branches for further study via `/timeline`.
Client-side script interactively responds to checkboxes' events
and constructs a special hyperlink in the submenu.
Clicking this hyperlink loads a `/timeline` page that shows
only these selected branches (and the related check-ins).
_Potential Workaround:_ A user can manually construct an appropriate
regular expession and put it into the "Tag Filter" entry of the
`/timeline` page (in its advanced mode).
----
## <a id="future"></a>Future Plans for JavaScript in Fossil
As of mid-2020, the informal provisional plan is to increase Fossil
UI's use of JavaScript considerably compared to its historically minimal
uses. To that end, a framework of Fossil-centric APIs is being developed
|
| ︙ | ︙ |
Changes to www/quickstart.wiki.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 |
[/help/clone | fossil clone])
<li>Check out a local tree. ([/help/open | fossil open])
<li>Perform operations on the repository (including repository
configuration).
</ul>
Fossil can be entirely driven from the command line. Many features
| | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
[/help/clone | fossil clone])
<li>Check out a local tree. ([/help/open | fossil open])
<li>Perform operations on the repository (including repository
configuration).
</ul>
Fossil can be entirely driven from the command line. Many features
can also be conveniently accessed from the built-in web user interface.
<p>The following sections give a brief overview of these
operations.</p>
<h2 id="new">Starting A New Project</h2>
<p>To start a new project with fossil create a new empty repository
|
| ︙ | ︙ | |||
240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# Original text<br>
</tt></b>
</blockquote>
<p>"fossil diff" is the difference between your tree on disk now and as the tree was
when you did "fossil open". An open is the first checkout from a repository
into a new directory. </p>
<p>To commit your changes to a local-only repository:</p>
<blockquote>
<b>
fossil commit </b><i>(... Fossil will start your editor, if defined)</i><b><br><tt>
# Enter a commit message for this check-in. Lines beginning with # are ignored.<br>
#<br>
| > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
# Original text<br>
</tt></b>
</blockquote>
<p>"fossil diff" is the difference between your tree on disk now and as the tree was
when you did "fossil open". An open is the first checkout from a repository
into a new directory. </p>
<p>To see the most recent changes made to the repository by other users, use "fossil timeline" to
find out the most recent commit, and then "fossil diff" between that commit and the
current tree: </p>
<blockquote>
<b>
fossil timeline <br><tt>
=== 2021-03-28 === <br>
03:18:54 [ad75dfa4a0] *CURRENT* Added details to frobnicate command (user: user-one tags: trunk) <br>
=== 2021-03-27 === <br>
23:58:05 [ab975c6632] Update README.md. (user: user-two tags: trunk) <br>
⋮ <br>
</tt><br>
fossil diff --from current --to ab975c6632 <br><tt>
Index: frobnicate.c<br>
============================================================<br>
--- frobnicate.c<br>
+++ frobnicate.c<br>
@@ -1,10 +1,11 @@<br>
+/* made a change to the source file */<br>
# Original text<br>
</tt></b>
</blockquote>
"current" is an alias for the checkout version, so the command
"fossil diff --from ad75dfa4a0 --to ab975c6632" gives identical results.
<p>To commit your changes to a local-only repository:</p>
<blockquote>
<b>
fossil commit </b><i>(... Fossil will start your editor, if defined)</i><b><br><tt>
# Enter a commit message for this check-in. Lines beginning with # are ignored.<br>
#<br>
|
| ︙ | ︙ | |||
475 476 477 478 479 480 481 | <blockquote> <b>[/help/server | fossil server]</b> <i>repository-filename</i><br> <b>[/help/ui | fossil ui]</b> <i>repository-filename</i> </blockquote> <p>The <i>repository-filename</i> can be omitted when these commands | | | | > | > | > > > > > > | | | > > > > > > > > | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | <blockquote> <b>[/help/server | fossil server]</b> <i>repository-filename</i><br> <b>[/help/ui | fossil ui]</b> <i>repository-filename</i> </blockquote> <p>The <i>repository-filename</i> can be omitted when these commands are run from within an open check-out, which is a particularly useful shortcut with the <b>fossil ui</b> command. <p>The <b>ui</b> command is intended for accessing the web user interface from a local desktop. (We sometimes call this mode "Fossil UI.") The <b>ui</b> command differs from the <b>server</b> command by binding to the loopback IP address only (thus making the web UI visible only on the local machine) and by automatically starting your default web browser, pointing it at the running UI server. The localhost restriction exists because it also gives anyone who can access the resulting web UI full control over the repository. (This is the [./caps/admin-v-setup.md#apsu | all-powerful Setup capabliity].)</p> <p>For cross-machine collaboration, use the <b>server</b> command instead, which binds on all IP addresses, does not try to start a web browser, and enforces [./caps/ | Fossil's role-based access control system].</p> <p>Servers are also easily configured as: <ul> <li>[./server/any/inetd.md|inetd] <li>[./server/debian/service.md|systemd] <li>[./server/any/cgi.md|CGI] <li>[./server/any/scgi.md|SCGI] </ul> <p>…along with [./server/#matrix | several other options].</p> <p>The [./selfhost.wiki | self-hosting fossil repositories] use CGI. <p>You might <i>need</i> to set up a server, whether you know it yet or not. See the [./server/whyuseaserver.wiki | Benefits of a Fossil Server] article for details.</p> <h2 id="proxy">HTTP Proxies</h2> <p>If you are behind a restrictive firewall that requires you to use an HTTP proxy to reach the internet, then you can configure the proxy in three different ways. You can tell fossil about your proxy using a command-line option on commands that use the network, |
| ︙ | ︙ |
Changes to www/rebaseharm.md.
| ︙ | ︙ | |||
291 292 293 294 295 296 297 | system clocks, so they are not unique to rebase, but they are very confusing and so best avoided. The other option is to provide new unique timestamps for C3' and C5' but then you lose the information about when those check-ins were originally created, which can make historical analysis of changes more difficult. It might also complicate the legal defense of prior art claims. | | < < < < < < | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | system clocks, so they are not unique to rebase, but they are very confusing and so best avoided. The other option is to provide new unique timestamps for C3' and C5' but then you lose the information about when those check-ins were originally created, which can make historical analysis of changes more difficult. It might also complicate the legal defense of prior art claims. ## <a name="lying"></a>5.0 Rebase misrepresents the project history By discarding parentage information, rebase attempts to deceive the reader about how the code actually came together. Git’s rebase feature is more than just an alternative to merging: it also provides mechanisms for changing the project history in order to make editorial changes. Fossil shows that you can get similar effects without modifying historical records, allowing users to: 1. Edit check-in comments to fix typos or enhance clarity 2. Attach supplemental notes to check-ins or whole branches |
| ︙ | ︙ |
Changes to www/server/index.html.
| ︙ | ︙ | |||
254 255 256 257 258 259 260 |
<td class="doc">❌</td>
<td class="doc"><a href="any/stunnel.md">✅</a></td>
<td class="doc"><a href="any/cgi.md">✅</a></td>
<td class="doc"><a href="any/scgi.md">✅</a></td>
<td class="doc"><a href="openbsd/fastcgi.md">✅</a></td>
<td class="doc"><a href="any/althttpd.md">✅</a></td>
<td class="doc">❌</td>
| | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
<td class="doc">❌</td>
<td class="doc"><a href="any/stunnel.md">✅</a></td>
<td class="doc"><a href="any/cgi.md">✅</a></td>
<td class="doc"><a href="any/scgi.md">✅</a></td>
<td class="doc"><a href="openbsd/fastcgi.md">✅</a></td>
<td class="doc"><a href="any/althttpd.md">✅</a></td>
<td class="doc">❌</td>
<td class="doc"><a href="openbsd/service.wiki">✅</a></td>
</tr>
<tr>
<th class="host"><a href="windows/">Windows</a></th>
<td class="doc"><a href="windows/none.md">✅</a></td>
<td class="doc">❌</td>
<td class="doc"><a href="windows/stunnel.md">✅</a></td>
|
| ︙ | ︙ |
Changes to www/server/openbsd/fastcgi.md.
| ︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
directory and log file—making the latter owned by the `www` user, and
the script executable.
```console
$ doas mkdir /var/www/htdocs/fsl.domain.tld
$ doas touch /var/www/logs/fossil.log
$ doas chown www /var/www/logs/fossil.log
$ doas chmod 755 /var/www/cgi-bin/scm
```
## <a name="chroot"></a>Setup chroot
Fossil needs both `/dev/random` and `/dev/null`, which aren't accessible
from within the chroot, so need to be constructed; `/var`, however, is
| > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
directory and log file—making the latter owned by the `www` user, and
the script executable.
```console
$ doas mkdir /var/www/htdocs/fsl.domain.tld
$ doas touch /var/www/logs/fossil.log
$ doas chown www /var/www/logs/fossil.log
$ doas chmod 660 /var/www/logs/fossil.log
$ doas chmod 755 /var/www/cgi-bin/scm
```
## <a name="chroot"></a>Setup chroot
Fossil needs both `/dev/random` and `/dev/null`, which aren't accessible
from within the chroot, so need to be constructed; `/var`, however, is
|
| ︙ | ︙ | |||
102 103 104 105 106 107 108 | The same user that executes the fossil binary must have writable access to the repository directory that resides within the chroot; on OpenBSD this is `www`. In addition, grant repository directory ownership to the user who will push to, pull from, and create repositories. ```console $ doas chown -R user:www /var/www/htdocs/fsl.domain.tld | | | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | The same user that executes the fossil binary must have writable access to the repository directory that resides within the chroot; on OpenBSD this is `www`. In addition, grant repository directory ownership to the user who will push to, pull from, and create repositories. ```console $ doas chown -R user:www /var/www/htdocs/fsl.domain.tld $ doas chmod 770 /var/www/htdocs/fsl.domain.tld ``` ## <a name="httpdconfig"></a>Configure httpd On OpenBSD, [httpd.conf(5)][httpd] is the configuration file for `httpd`. To setup the server to serve all Fossil repositores within the directory specified in the CGI script, and automatically redirect |
| ︙ | ︙ |
Changes to www/server/openbsd/index.md.
1 2 3 4 5 | # Debian/Ubuntu Specific Fossil Service Options - [Serving Fossil under OpenBSD’s `httpd` via FastCGI](./fastcgi.md) *[Return to the top-level Fossil server article.](../)* | > | 1 2 3 4 5 6 | # Debian/Ubuntu Specific Fossil Service Options - [Serving Fossil under OpenBSD’s `httpd` via FastCGI](./fastcgi.md) - [Running Fossil as a service on OpenBSD](./service.wiki) *[Return to the top-level Fossil server article.](../)* |
Added www/server/openbsd/service.wiki.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
<title>Serving via rc on OpenBSD</title>
OpenBSD provides [https://man.openbsd.org/rc.subr.8|rc.subr(8)],
a framework for writing [https://man.openbsd.org/rc.8|rc(8)] scripts.
<h2>Creating the daemon</h2>
Create the file /etc/rc.d/fossil with contents like the following.
<blockquote><pre>
#!/bin/ksh
daemon="/usr/local/bin/fossil" # fossil executable
daemon_user="_fossil" # user to run fossil as
daemon_flags="server /home/_fossil/example --repolist --port 8888" # fossil command
. /etc/rc.d/rc.subr
# pexp="$daemon server .*" # See below.
rc_bg=YES # Run in the background, since fossil serve does not daemonize itself
rc_cmd $1
</pre></blockquote>
<h3>pexp</h3>
You may need to uncomment the "pexp=". rc.subr typically
finds the daemon process based by matching the process name and argument list.
Without the "pexp=" line, rc.subr would look for this exact command:
<blockquote><pre>
/usr/local/bin/fossil server /home/_fossil/example --repolist --port 8888
</pre></blockquote>
Depending on the arguments and their order, fossil may rewrite the arguments
for display in the process listing ([https://man.openbsd.org/ps.1|ps(1)]),
so rc.subr may fail to find the process through the default match. The example
above does not get rewritten, but the same commands in a different order can
be rewritten.
For example, when I switch the order of the arguments in "daemon_flags",
<blockquote><pre>
/usr/local/bin/fossil server --repolist --port 8888 /home/_fossil/example
</pre></blockquote>
the process command is changed to this.
<blockquote><pre>
/usr/local/bin/fossil server /home/_fossil/example /home/_fossil/example 8888 /home/_fossil/example
</pre></blockquote>
The commented "pexp=" line instructs rc.subr to choose the process whose
command and arguments text starts with this:
<blockquote><pre>
/usr/local/bin/fossil server
</pre></blockquote>
<h2>Enabling the daemon</h2>
Once you have created /etc/rc.d/fossil, run these commands.
<blockquote><pre>
rcctl enable fossil # add fossil to pkg_scripts in /etc/rc.conf.local
rcctl start fossil # start the daemon now
</pre></blockquote>
The daemon should now be running and set to start at boot.
<h2>Multiple daemons</h2>
You may want to serve multiple fossil instances with different options.
For example,
* If different users own different repositories, you may want different users
to serve different repositories.
* You may want to serve different repositories on different ports so you can
control them differently with, for example, HTTP reverse proxies or
[https://man.openbsd.org/pf.4|pf(4)].
To run multiple fossil daemons, create multiple files in /etc/rc.d, and
enable each of them. Here are two approaches for creating
the files in /etc/rc.d: Symbolic links and copies.
<h3>Symbolic links</h3>
Suppose you want to run one fossil daemon as user "user1" on port 8881
and another as user "user2" on port 8882. Create the files with
[https://man.openbsd.org/ln.1|ln(1)], and configure them to run different
fossil commands.
<blockquote><pre>
cd /etc/rc.d
ln -s fossil fossil1
ln -s fossil fossil2
rcctl enable fossil1 fossil2
rcctl set fossil1 user user1
rcctl set fossil2 user user2
rcctl set fossil1 flags 'server /home/user1/repo1.fossil --port 8881'
rcctl set fossil2 flags 'server /home/user2/repo2.fossil --port 8882'
rcctl start fossil1 fossil2
</pre></blockquote>
<h3>Copies</h3>
You may want to run fossil daemons that are too different to configure
just with [https://man.openbsd.org/rcctl.8|rcctl(8)].
In particular, you can't change the "pexp" with rcctl.
If you want to run fossil commands that are more different,
you may prefer to create separate files in /etc/rc.d.
Replace "ln -s" above with "cp" to accomplish this.
<blockquote><pre>
cp /etc/rc.d/fossil /etc/rc.d/fossil-user1
cp /etc/rc.d/fossil /etc/rc.d/fossil-user2
</pre></blockquote>
You can still use commands like "rcctl set fossil-user1 flags", but you
can also edit the "/etc/rc.d/fossil-user1" file.
|
Changes to www/server/whyuseaserver.wiki.
1 2 3 4 5 6 7 | <title>Benefits of a Fossil Server</title> <h2>No Server Required</h2> Fossil does not require a central server. Data sharing and synchronization can be entirely peer-to-peer. Fossil uses | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <title>Benefits of a Fossil Server</title> <h2>No Server Required</h2> Fossil does not require a central server. Data sharing and synchronization can be entirely peer-to-peer. Fossil uses [https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type | conflict-free replicated data types] to ensure that (in the limit) all participating peers see the same content. <h2>But, a Server Can Be Useful</h2> Fossil does not require a server, but a server can be very useful. Here are a few reasons to set up a Fossil server for your project: |
| ︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 |
corruption can be fixed with a fresh clone. Ultimately, this
is an argument for off-machine backups, which returns us to reason
#4 above.<p>
Sections 3.2 and the entirety of section 7 are no concern with
Fossil at all, since it's primarily written by the creator and
primary maintainer of SQLite, so you can be certain Fossil doesn't
actively pursue coding strategies known to risk database corruption.<p>
6. <b>A server allows [../caps/ | Fossil's RBAC system] to work.</b><p>
The role-based access control (RBAC) system in Fossil only works
when the remote system is on the other side of an HTTP barrier.
([../caps/#webonly | Details].) If you want its benefits, you need
a Fossil server setup of some kind.
| > > > > > > > > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
corruption can be fixed with a fresh clone. Ultimately, this
is an argument for off-machine backups, which returns us to reason
#4 above.<p>
Sections 3.2 and the entirety of section 7 are no concern with
Fossil at all, since it's primarily written by the creator and
primary maintainer of SQLite, so you can be certain Fossil doesn't
actively pursue coding strategies known to risk database corruption.<p>
<p>For another take on this topic, see the article
"[https://sqlite.org/useovernet.html | SQLite Over a Network,
Caveats and Considerations]". Fossil runs in rollback mode by
default per recommendation #3 at the end of that article, and a
Fossil server operates as a network proxy for the underlying
SQLite repository DB per recommendation #2. This <i>may</i> permit
you to safely switch it into WAL mode (<b>fossil rebuild --wal</b>)
depending on the underlying storage used by the server itself.</p>
6. <b>A server allows [../caps/ | Fossil's RBAC system] to work.</b><p>
The role-based access control (RBAC) system in Fossil only works
when the remote system is on the other side of an HTTP barrier.
([../caps/#webonly | Details].) If you want its benefits, you need
a Fossil server setup of some kind.
|