Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge from trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | th1-doc-vars |
Files: | files | file ages | folders |
SHA3-256: |
1cf5c43ea5e11791f15afcbefa04312f |
User & Date: | george 2021-06-15 21:27:15.269 |
Context
2021-08-15
| ||
23:13 | Merge from trunk ... (check-in: 5b67899d user: george tags: th1-doc-vars) | |
2021-06-15
| ||
21:27 | Merge from trunk ... (check-in: 1cf5c43e user: george tags: th1-doc-vars) | |
17:20 | Factored out an extraneous var from [1bb06c94]. No functional changes. ... (check-in: e0686dda user: stephan tags: trunk) | |
2021-04-10
| ||
04:30 | Fix dereferencing of NULL-pointer in 'pWiki' for the case when non-existent wiki page is requested. ... (check-in: 735a7051 user: george tags: th1-doc-vars) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.16 |
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/ardoise/header.txt.
︙ | ︙ | |||
24 25 26 27 28 29 30 | <ul> <th1> html "<li><a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a></li>\n" builtin_request_js hbmenu.js set once 1 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <ul> <th1> html "<li><a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a></li>\n" builtin_request_js hbmenu.js set once 1 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {$once && [string match $url\[/?#\]* /$current_page/]} { set class "$class active" set once 0 } html "<li class='$class'>" if {[string match /* $url]} {set url $home$url} html "<a href='$url'>$name</a></li>\n" } </th1></ul> |
︙ | ︙ |
Changes to skins/blitz/header.txt.
︙ | ︙ | |||
25 26 27 28 29 30 31 | <div class="mainmenu"> <ul><th1> html "<li><a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a></li>\n" builtin_request_js hbmenu.js set once 1 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue | | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <div class="mainmenu"> <ul><th1> html "<li><a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a></li>\n" builtin_request_js hbmenu.js set once 1 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {$once && [string match $url\[/?#\]* /$current_page/]} { set class "active $class" set once 0 } html "<li class='$class'>" if {[string match /* $url]} {set url $home$url} html "<a href='$url'>$name</a></li>\n" } </th1></ul> |
︙ | ︙ |
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/bootstrap/header.txt.
︙ | ︙ | |||
43 44 45 46 47 48 49 | <th1> set once 1 set sitemap 0 set is_index [expr [string compare [string range $current_page 0 4] "index"]==0] set is_home [expr [string compare [string range $current_page 0 [expr [string length $index_page]-1] ] $index_page]==0] foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue | | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <th1> set once 1 set sitemap 0 set is_index [expr [string compare [string range $current_page 0 4] "index"]==0] set is_home [expr [string compare [string range $current_page 0 [expr [string length $index_page]-1] ] $index_page]==0] foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {$once && [string match $url\[/?#\]* /$current_page/]} { set class "active $class" set once 0 } html "<li class='$class'>" if {[string match /* $url]} {set url $home$url} if {[string match *sitemap* $url]} {set sitemap 1} html "<a href='$url'>$name</a></li>\n" } |
︙ | ︙ |
Changes to skins/darkmode/css.txt.
︙ | ︙ | |||
83 84 85 86 87 88 89 | } a:visited {opacity: 0.8} div.mainmenu a, div.submenu a, div.sectionmenu>a.button, div.submenu label, div.footer a { padding: 0.15em 0.5em; } | | > > | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | } a:visited {opacity: 0.8} div.mainmenu a, div.submenu a, div.sectionmenu>a.button, div.submenu label, div.footer a { padding: 0.15em 0.5em; } div.mainmenu a.active { border-bottom: 1px solid #FF4500f0; } a:hover, a:visited:hover { background-color: #FF4500f0; color: rgba(24,24,24,0.8); border-radius: 0.1em; } .fileage tr:hover, |
︙ | ︙ | |||
551 552 553 554 555 556 557 | 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 } | > > > > > | 553 554 555 556 557 558 559 560 561 562 563 564 | 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/darkmode/header.txt.
︙ | ︙ | |||
15 16 17 18 19 20 21 | <div class="mainmenu"> <th1> html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>" builtin_request_js hbmenu.js foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <div class="mainmenu"> <th1> html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>" builtin_request_js hbmenu.js foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { if {[string match $url\[/?#\]* /$current_page/]} { set class "active $class" } set url $home$url } html "<a href='$url' class='$class'>$name</a>\n" } </th1></div> |
︙ | ︙ |
Changes to skins/default/css.txt.
︙ | ︙ | |||
265 266 267 268 269 270 271 | } .title { padding-top: 0px; padding-bottom: 0px; } .status {padding-top: 0px;} .mainmenu a { | | | | 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 | } .title { padding-top: 0px; padding-bottom: 0px; } .status {padding-top: 0px;} .mainmenu a { padding: 8px 10px; } .mainmenu { padding: 10px; } } @media screen and (min-width: 600px) { /* Spacing for desktop */ body { padding-left: 20px; padding-right: 20px; } .title { padding-top: 10px; padding-bottom: 10px; } .status {padding-top: 30px;} .mainmenu a { padding: 8px 20px; } .mainmenu { padding: 10px; } } |
Changes to skins/default/header.txt.
︙ | ︙ | |||
11 12 13 14 15 16 17 | <div class="mainmenu"> <th1> html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>" builtin_request_js hbmenu.js foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <div class="mainmenu"> <th1> html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>☰</a>" builtin_request_js hbmenu.js foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { if {[string match $url\[/?#\]* /$current_page/]} { set class "active $class" } set url $home$url } html "<a href='$url' class='$class'>$name</a>\n" } </th1></div> |
︙ | ︙ |
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.
︙ | ︙ | |||
1122 1123 1124 1125 1126 1127 1128 | } .fossil-PopupWidget, .fossil-tooltip.help-buttonlet-content { background-color: #111; border: 1px solid rgba(255,255,255,0.5); } | > > > | > > > > > | 1122 1123 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 | } .fossil-PopupWidget, .fossil-tooltip.help-buttonlet-content { background-color: #111; border: 1px solid rgba(255,255,255,0.5); } .fossil-PopupWidget a, .fossil-PopupWidget a:visited { color: white; } div.forumSel { background-color: #663399; } div.forumPostBody blockquote { border-width: 1pt; border-style: solid; 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 skins/xekri/header.txt.
︙ | ︙ | |||
92 93 94 95 96 97 98 | updateClock(); </script> <div class="mainmenu"><th1> set sitemap 0 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { | | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | updateClock(); </script> <div class="mainmenu"><th1> set sitemap 0 foreach {name url expr class} $mainmenu { if {![capexpr $expr]} continue if {[string match /* $url]} { if {[string match $url\[/?#\]* /$current_page/]} { set class "active $class" } set url $home$url } html "<a href='$url' class='$class'>$name</a>\n" if {[string match */sitemap $url]} {set sitemap 1} } if {!$sitemap} { |
︙ | ︙ |
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/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 | ** 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'> |
︙ | ︙ | |||
181 182 183 184 185 186 187 | @ </div> @ </div> @ </form> @ <div id='chat-messages-wrapper'> /* New chat messages get inserted immediately after this element */ @ <span id='message-inject-point'></span> @ </div> | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | @ </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') |
︙ | ︙ | |||
209 210 211 212 213 214 215 | } /* Definition of repository tables used by chat */ static const char zChatSchema1[] = @ CREATE TABLE repository.chat( @ msgid INTEGER PRIMARY KEY AUTOINCREMENT, | | | | | | | | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | } /* Definition of repository tables used by chat */ static const char zChatSchema1[] = @ CREATE TABLE repository.chat( @ msgid INTEGER PRIMARY KEY AUTOINCREMENT, @ mtime JULIANDAY, -- Time for this entry - Julianday Zulu @ lmtime TEXT, -- Client YYYY-MM-DDZHH:MM:SS when message originally sent @ xfrom TEXT, -- Login of the sender @ xmsg TEXT, -- Raw, unformatted text of the message @ fname TEXT, -- Filename of the uploaded file, or NULL @ fmime TEXT, -- MIMEType of the upload file, or NULL @ mdel INT, -- msgid of another message to delete @ file BLOB -- Text of the uploaded file, or NULL @ ); ; /* ** Make sure the repository data tables used by chat exist. Create them ** if they do not. |
︙ | ︙ | |||
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | ** 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); } |
︙ | ︙ | |||
477 478 479 480 481 482 483 | ** The reply from this webpage is JSON that describes the new content. ** Format of the json: ** ** | { ** | "msgs":[ ** | { ** | "msgid": integer // message id | | | | 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | ** The reply from this webpage is JSON that describes the new content. ** Format of the json: ** ** | { ** | "msgs":[ ** | { ** | "msgid": integer // message id ** | "mtime": text // When sent: YYYY-MM-DDTHH:MM:SSZ ** | "lmtime: text // Sender's client-side YYYY-MM-DDTHH:MM:SS ** | "xfrom": text // Login name of sender ** | "uclr": text // Color string associated with the user ** | "xmsg": text // HTML text of the message ** | "fsize": integer // file attachment size in bytes ** | "fname": text // Name of file attachment ** | "fmime": text // MIME-type of file attachment ** | "mdel": integer // message id of prior message to delete |
︙ | ︙ | |||
596 597 598 599 600 601 602 | 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.
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | }, false); resized(); return resized; })(); fossil.FRK = ForceResizeKludge/*for debugging*/; const Chat = (function(){ const cs = { e:{/*map of certain DOM elements.*/ messageInjectPoint: E1('#message-inject-point'), pageTitle: E1('head title'), loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */, inputWrapper: E1("#chat-input-area"), fileSelectWrapper: E1('#chat-input-file-area'), messagesWrapper: E1('#chat-messages-wrapper'), | > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | }, false); resized(); return resized; })(); fossil.FRK = ForceResizeKludge/*for debugging*/; const Chat = (function(){ const cs = { verboseErrors: false /* if true then certain, mostly extraneous, error messages may be sent to the console. */, e:{/*map of certain DOM elements.*/ messageInjectPoint: E1('#message-inject-point'), pageTitle: E1('head title'), loadOlderToolbar: undefined /* the load-posts toolbar (dynamically created) */, inputWrapper: E1("#chat-input-area"), fileSelectWrapper: E1('#chat-input-file-area'), messagesWrapper: E1('#chat-messages-wrapper'), |
︙ | ︙ | |||
224 225 226 227 228 229 230 | 'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false) ); }else{ eMsg.scrollIntoView(false); } return this; }, | | | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | 'load', ()=>(this.e.newestMessage || eMsg).scrollIntoView(false) ); }else{ eMsg.scrollIntoView(false); } return this; }, /* Injects DOM 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); |
︙ | ︙ | |||
376 377 378 379 380 381 382 | } 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 | | | 378 379 380 381 382 383 384 385 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 this. */ setNewMessageSound: function f(uri){ delete this.playNewMessageSound.audio; this.playNewMessageSound.uri = uri; this.settings.set('audible-alert', !!uri); return this; } |
︙ | ︙ | |||
407 408 409 410 411 412 413 | } 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; | < | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | } 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(). |
︙ | ︙ | |||
431 432 433 434 435 436 437 | 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(), | | | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | 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+'"]'); }; |
︙ | ︙ | |||
602 603 604 605 606 607 608 | d.getFullYear(),'-',pad2(d.getMonth()+1/*sigh*/), '-',pad2(d.getDate()), ' ',pad2(d.getHours()),':',pad2(d.getMinutes()), ':',pad2(d.getSeconds()) ].join(''); }; cf.prototype = { | < < < > > | | | 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 | 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( |
︙ | ︙ | |||
681 682 683 684 685 686 687 688 689 690 691 692 693 694 | // 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 */ | > > > | 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | // 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 */ |
︙ | ︙ | |||
733 734 735 736 737 738 739 740 741 742 743 744 745 746 | const btnDeleteGlobal = D.button("Delete globally"); D.append(toolbar, btnDeleteGlobal); btnDeleteGlobal.addEventListener('click', function(){ self.hide(); Chat.deleteMessage(eMsg); }); } }/*refresh()*/ }); f.popup.installHideHandlers(); f.popup.hide = function(){ delete this._eMsg; D.clearElement(this.e); return this.show(false); | > > > > > > > > > > > > > | 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 | const btnDeleteGlobal = D.button("Delete globally"); D.append(toolbar, btnDeleteGlobal); btnDeleteGlobal.addEventListener('click', function(){ self.hide(); Chat.deleteMessage(eMsg); }); } if(eMsg.dataset.xfrom){ /* Add a link to the /timeline filtered on this user. */ const toolbar2 = D.addClass(D.div(), 'toolbar'); D.append(this.e, toolbar2); const timelineLink = D.attr( D.a(F.repoUrl('timeline',{ u: eMsg.dataset.xfrom, y: 'a' }), "User's Timeline"), 'target', '_blank' ); D.append(toolbar2, timelineLink); } }/*refresh()*/ }); f.popup.installHideHandlers(); f.popup.hide = function(){ delete this._eMsg; D.clearElement(this.e); return this.show(false); |
︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 | }, responseType: "json", // Disable the ajax start/end handling for this long-polling op: beforesend: function(){}, aftersend: function(){}, onerror:function(err){ Chat._isBatchLoading = false; | | | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 | }, responseType: "json", // Disable the ajax start/end handling for this long-polling op: beforesend: function(){}, aftersend: function(){}, onerror:function(err){ Chat._isBatchLoading = false; if(Chat.verboseErrors) console.error(err); /* ^^^ we don't use Chat.reportError() here b/c the polling fails exepectedly when it times out, but is then immediately resumed, and reportError() produces a loud error message. */ afterFetch(); }, onload:function(y){ newcontent(y); |
︙ | ︙ |
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.
︙ | ︙ | |||
862 863 864 865 866 867 868 | db_find_and_open_repository(0,0); db_prepare(&err, "INSERT INTO repository.config(name) VALUES(NULL);"); db_exec(&err); } /* ** COMMAND: test-db-prepare | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | db_find_and_open_repository(0,0); db_prepare(&err, "INSERT INTO repository.config(name) VALUES(NULL);"); db_exec(&err); } /* ** COMMAND: test-db-prepare ** Usage: %fossil test-db-prepare ?OPTIONS? SQL-STATEMENT ** ** Options: ** ** --auth-report Enable the ticket report query authorizer. ** --auth-ticket Enable the ticket schema query authorizer. ** ** Invoke db_prepare() on the SQL input. Report any errors encountered. ** This command is used to verify error detection logic in the db_prepare() ** utility routine. */ void db_test_db_prepare(void){ const int fAuthReport = find_option("auth-report",0,0)!=0; const int fAuthSchema = find_option("auth-ticket",0,0)!=0; char * zReportErr = 0; /* auth-report error string. */ int nSchemaErr = 0; /* Number of auth-ticket errors. */ Stmt err; if(fAuthReport + fAuthSchema > 1){ fossil_fatal("Only one of --auth-report or --auth-ticket " "may be used."); } db_find_and_open_repository(0,0); verify_all_options(); if( g.argc!=3 ) usage("?OPTIONS? SQL"); if(fAuthReport){ report_restrict_sql(&zReportErr); }else if(fAuthSchema){ ticket_restrict_sql(&nSchemaErr); } db_prepare(&err, "%s", g.argv[2]/*safe-for-%s*/); db_finalize(&err); if(fAuthReport){ report_unrestrict_sql(); if(zReportErr){ fossil_warning("Report authorizer error: %s\n", zReportErr); fossil_free(zReportErr); } }else if(fAuthSchema){ ticket_unrestrict_sql(); if(nSchemaErr){ fossil_warning("Ticket schema authorizer error count: %d\n", nSchemaErr); } } } /* ** Print the output of one or more SQL queries on standard output. ** This routine is used for debugging purposes only. */ int db_debug(const char *zSql, ...){ |
︙ | ︙ | |||
1709 1710 1711 1712 1713 1714 1715 | */ 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"); | | | | | | > | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 | */ 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; } /* |
︙ | ︙ |
Changes to src/default.css.
︙ | ︙ | |||
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 | border-radius: 0.25em; background-color: rgba(20, 20, 20, 1) /* problem: if we inherit the color it may either be transparent or inherit translucency via the skin, leaving it unreadable. Since we set the bg color we must also set the fg color. */; color: rgba(235, 235, 235, 0.9); } .fossil-toast-message.error, .fossil-toast-message.warning { background: yellow; } .fossil-toast-message.error { font-weight: bold; | > > > > | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 | border-radius: 0.25em; background-color: rgba(20, 20, 20, 1) /* problem: if we inherit the color it may either be transparent or inherit translucency via the skin, leaving it unreadable. Since we set the bg color we must also set the fg color. */; color: rgba(235, 235, 235, 0.9); } .fossil-PopupWidget a, .fossil-PopupWidget a:visited { color: initial; } .fossil-toast-message.error, .fossil-toast-message.warning { background: yellow; } .fossil-toast-message.error { font-weight: bold; |
︙ | ︙ | |||
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; | > > > > > > | 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 | 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; } } | > > > > > > > > > > > > > > > > > > > > | 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 | 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.
︙ | ︙ | |||
2162 2163 2164 2165 2166 2167 2168 | #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">\ |
︙ | ︙ | |||
534 535 536 537 538 539 540 | @ updated by %z(href("%R/forumpost/%S?%s",p->pEditNext->zUuid,zQuery))\ @ %d(p->pEditNext->sid)\ @ .%0*d(fossil_num_digits(p->nEdit))(p->pEditNext->rev)</a> } /* Provide a link to select the individual post. */ if( !bSelect ){ | | | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | @ updated by %z(href("%R/forumpost/%S?%s",p->pEditNext->zUuid,zQuery))\ @ %d(p->pEditNext->sid)\ @ .%0*d(fossil_num_digits(p->nEdit))(p->pEditNext->rev)</a> } /* Provide a link to select the individual post. */ if( !bSelect ){ @ %z(href("%R/forumpost/%!S?%s",p->zUuid,zQuery))[link]</a> } /* Provide a link to the raw source code. */ if( !bUnf ){ @ %z(href("%R/forumpost/%!S?raw",p->zUuid))[source]</a> } @ </h3> } /* Check if this post is approved, also if it's by the current user. */ bPrivate = content_is_private(p->fpid); bSameUser = login_is_individual() |
︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 | int froot; Manifest *pPost = 0; Manifest *pRootPost = 0; const char *zMimetype = 0; const char *zContent = 0; const char *zTitle = 0; char *zDate = 0; int isCsrfSafe; int isDelete = 0; login_check_credentials(); if( !g.perm.WrForum ){ login_needed(g.anon.WrForum); return; } | > | | 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 | int froot; Manifest *pPost = 0; Manifest *pRootPost = 0; const char *zMimetype = 0; const char *zContent = 0; const char *zTitle = 0; char *zDate = 0; const char *zFpid = PD("fpid",""); int isCsrfSafe; int isDelete = 0; login_check_credentials(); if( !g.perm.WrForum ){ login_needed(g.anon.WrForum); return; } fpid = symbolic_name_to_rid(zFpid, "f"); if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ webpage_error("Missing or invalid fpid query parameter"); } froot = db_int(0, "SELECT froot FROM forumpost WHERE fpid=%d", fpid); if( froot==0 || (pRootPost = manifest_get(froot, CFTYPE_FORUM, 0))==0 ){ webpage_error("fpid does not appear to be a forum post: \"%d\"", fpid); } |
︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 | char *zDisplayName; zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE); zContent = PDT("content",""); style_header("Reply"); if( pRootPost->zThreadTitle ){ @ <h1>Thread: %h(pRootPost->zThreadTitle)</h1> } | | > > > | | 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 | char *zDisplayName; zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE); zContent = PDT("content",""); style_header("Reply"); if( pRootPost->zThreadTitle ){ @ <h1>Thread: %h(pRootPost->zThreadTitle)</h1> } @ <h2>Replying To: @ <a href="%R/forumpost/%!S(zFpid)" target="_blank">%S(zFpid)</a> @ <a href="%R/forumpost/%!S(zFpid)?raw" target="_blank">[source]</a> @ </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); } |
︙ | ︙ |
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.
︙ | ︙ | |||
250 251 252 253 254 255 256 257 258 259 260 261 262 263 | ** g.url.name Name of the proxy server, if proxying. ** pUrlData->port TCP/IP port to use. Ex: 80 ** ** Return the number of errors. */ int ssl_open(UrlData *pUrlData){ X509 *cert; ssl_global_init(); if( pUrlData->useProxy ){ int rc; char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port); BIO *sBio = BIO_new_connect(connStr); free(connStr); | > | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | ** g.url.name Name of the proxy server, if proxying. ** pUrlData->port TCP/IP port to use. Ex: 80 ** ** Return the number of errors. */ int ssl_open(UrlData *pUrlData){ X509 *cert; const char *zRemoteHost; ssl_global_init(); if( pUrlData->useProxy ){ int rc; char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port); BIO *sBio = BIO_new_connect(connStr); free(connStr); |
︙ | ︙ | |||
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | return 1; } pUrlData->path = pUrlData->proxyUrlPath; iBio = BIO_new_ssl(sslCtx, 1); BIO_push(iBio, sBio); }else{ iBio = BIO_new_ssl_connect(sslCtx); } if( iBio==NULL ) { ssl_set_errmsg("SSL: cannot open SSL (%s)", ERR_reason_error_string(ERR_get_error())); return 1; } BIO_get_ssl(iBio, &ssl); #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT) | > > | < < > > > > > > > > > > | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | return 1; } pUrlData->path = pUrlData->proxyUrlPath; iBio = BIO_new_ssl(sslCtx, 1); BIO_push(iBio, sBio); zRemoteHost = pUrlData->hostname; }else{ iBio = BIO_new_ssl_connect(sslCtx); zRemoteHost = pUrlData->name; } if( iBio==NULL ) { ssl_set_errmsg("SSL: cannot open SSL (%s)", ERR_reason_error_string(ERR_get_error())); return 1; } BIO_get_ssl(iBio, &ssl); #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT) if( !SSL_set_tlsext_host_name(ssl, zRemoteHost)){ fossil_warning("WARNING: failed to set server name indication (SNI), " "continuing without it.\n"); } #endif SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); #if OPENSSL_VERSION_NUMBER >= 0x010002000 if( !sslNoCertVerify ){ X509_VERIFY_PARAM *param = 0; param = SSL_get0_param(ssl); if( !X509_VERIFY_PARAM_set1_host(param, zRemoteHost, strlen(zRemoteHost)) ){ fossil_fatal("failed to set hostname."); } /* SSL_set_verify(ssl, SSL_VERIFY_PEER, 0); */ } #endif if( !pUrlData->useProxy ){ char *connStr = mprintf("%s:%d", pUrlData->name, pUrlData->port); BIO_set_conn_hostname(iBio, connStr); free(connStr); if( BIO_do_connect(iBio)<=0 ){ ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)", |
︙ | ︙ |
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" |
︙ | ︙ | |||
2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 | if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)" " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){ winfo_page(); }else if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)" " WHERE rid=%d AND tagname LIKE 'tkt-%%'", rid) ){ tinfo_page(); }else if( db_exists("SELECT 1 FROM plink WHERE cid=%d", rid) ){ ci_page(); }else if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){ ci_page(); }else if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){ ainfo_page(); }else | > > > > > < < < < < | 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 | if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)" " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){ winfo_page(); }else if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)" " WHERE rid=%d AND tagname LIKE 'tkt-%%'", rid) ){ tinfo_page(); }else if( db_table_exists("repository","forumpost") && db_exists("SELECT 1 FROM forumpost WHERE fpid=%d", rid) ){ forumthread_page(); }else if( db_exists("SELECT 1 FROM plink WHERE cid=%d", rid) ){ ci_page(); }else if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){ ci_page(); }else if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){ ainfo_page(); }else { artifact_page(); } } /* ** Do a comment comparison. |
︙ | ︙ |
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.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/pikchr.c.
︙ | ︙ | |||
7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 | return 2; } }else{ pToken->eType = T_LT; return 1; } } case '{': { int len, depth; i = 1; if( bAllowCodeBlock ){ depth = 1; while( z[i] && depth>0 ){ PToken x; | > > > > > > > > > > > > > > > > > > | 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 | return 2; } }else{ pToken->eType = T_LT; return 1; } } case 0xe2: { if( z[1]==0x86 ){ if( z[2]==0x90 ){ pToken->eType = T_LARROW; /* <- */ return 3; } if( z[2]==0x92 ){ pToken->eType = T_RARROW; /* -> */ return 3; } if( z[2]==0x94 ){ pToken->eType = T_LRARROW; /* <-> */ return 3; } } pToken->eType = T_ERROR; return 1; } case '{': { int len, depth; i = 1; if( bAllowCodeBlock ){ depth = 1; while( z[i] && depth>0 ){ PToken x; |
︙ | ︙ | |||
7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 | } if( depth ){ pToken->eType = T_ERROR; return 1; } pToken->eType = T_CODEBLOCK; return i; } default: { c = z[0]; if( c=='.' ){ unsigned char c1 = z[1]; if( islower(c1) ){ const PikWord *pFound; | > > > > > > > > > > > > > > > > > > > > > > > | 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 | } if( depth ){ pToken->eType = T_ERROR; return 1; } pToken->eType = T_CODEBLOCK; return i; } case '&': { static const struct { int nByte; /* Number of bytes in zEntity */ int eCode; /* Corresponding token code */ const char *zEntity; /* Name of the HTML entity */ } aEntity[] = { /* 123456789 1234567 */ { 6, T_RARROW, "→" }, /* Same as -> */ { 12, T_RARROW, "→" }, /* Same as -> */ { 6, T_LARROW, "←" }, /* Same as <- */ { 11, T_LARROW, "←" }, /* Same as <- */ { 16, T_LRARROW, "↔" }, /* Same as <-> */ }; unsigned int i; for(i=0; i<sizeof(aEntity)/sizeof(aEntity[0]); i++){ if( strncmp((const char*)z,aEntity[i].zEntity,aEntity[i].nByte)==0 ){ pToken->eType = aEntity[i].eCode; return aEntity[i].nByte; } } pToken->eType = T_ERROR; return 1; } default: { c = z[0]; if( c=='.' ){ unsigned char c1 = z[1]; if( islower(c1) ){ const PikWord *pFound; |
︙ | ︙ | |||
7958 7959 7960 7961 7962 7963 7964 | return TCL_OK; } #endif /* PIKCHR_TCL */ | | | 7999 8000 8001 8002 8003 8004 8005 8006 | return TCL_OK; } #endif /* PIKCHR_TCL */ #line 8031 "pikchr.c" |
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.
︙ | ︙ | |||
159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /*********************************************************************/ /* ** This is the SQLite authorizer callback used to make sure that the ** SQL statements entered by users do not try to do anything untoward. ** If anything suspicious is tried, set *(char**)pError to an error ** message obtained from malloc. */ static int report_query_authorizer( void *pError, int code, const char *zArg1, const char *zArg2, const char *zArg3, | > > > | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | /*********************************************************************/ /* ** This is the SQLite authorizer callback used to make sure that the ** SQL statements entered by users do not try to do anything untoward. ** If anything suspicious is tried, set *(char**)pError to an error ** message obtained from malloc. ** ** Use the "fossil test-db-prepare --auth-report SQL" command to perform ** manual testing of this authorizer. */ static int report_query_authorizer( void *pError, int code, const char *zArg1, const char *zArg2, const char *zArg3, |
︙ | ︙ | |||
197 198 199 200 201 202 203 | "tagxref", "ticket", "ticketchng", "unversioned", }; int lwr = 0; int upr = count(azAllowed) - 1; | | | | | | | > > > > | | > | 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 | "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; break; } } return rc; } /* ** Activate the ticket report query authorizer. Must be followed by an ** eventual call to report_unrestrict_sql(). */ void report_restrict_sql(char **pzErr){ db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report"); sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000); } void report_unrestrict_sql(void){ db_clear_authorizer(); |
︙ | ︙ | |||
966 967 968 969 970 971 972 | fossil_free((void *)azVals); return rc; } /* ** WEBPAGE: rptview ** | | | | < < < < | 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 | fossil_free((void *)azVals); return rc; } /* ** WEBPAGE: rptview ** ** Generate a report. The rn query parameter is the report number ** corresponding to REPORTFMT.RN. If the tablist query parameter exists, ** then the output consists of lines of tab-separated fields instead of ** an HTML table. */ void rptview_page(void){ int count = 0; int rn, rc; char *zSql; char *zTitle; char *zOwner; |
︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 | count = 0; if( !tabs ){ struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char *zQS = PD("QUERY_STRING",""); db_multi_exec("PRAGMA empty_result_callbacks=ON"); style_set_current_feature("report"); | | < < < < < < | | < < < | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | count = 0; if( !tabs ){ struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char *zQS = PD("QUERY_STRING",""); db_multi_exec("PRAGMA empty_result_callbacks=ON"); style_set_current_feature("report"); /* style_finish_page() should provide escaping via %h formatting */ if( zQS[0] ){ style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS); style_submenu_element("Reports","%R/reportlist?%s",zQS); } else { style_submenu_element("Raw","%R/%s?tablist=1",g.zPath); style_submenu_element("Reports","%R/reportlist"); } if( g.perm.Admin || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ style_submenu_element("Edit", "rptedit?rn=%d", rn); } if( g.perm.TktFmt ){ style_submenu_element("SQL", "rptsql?rn=%d",rn); } |
︙ | ︙ |
Changes to src/schema.c.
︙ | ︙ | |||
327 328 329 330 331 332 333 | @ -- @ CREATE TABLE phantom( @ rid INTEGER PRIMARY KEY -- Record ID of the phantom @ ); @ @ -- A record of orphaned delta-manifests. An orphan is a delta-manifest @ -- for which we have content, but its baseline-manifest is a phantom. | | | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | @ -- @ CREATE TABLE phantom( @ rid INTEGER PRIMARY KEY -- Record ID of the phantom @ ); @ @ -- A record of orphaned delta-manifests. An orphan is a delta-manifest @ -- for which we have content, but its baseline-manifest is a phantom. @ -- We have to track all orphan manifests so that when the baseline arrives, @ -- we know to process the orphaned deltas. @ CREATE TABLE orphan( @ rid INTEGER PRIMARY KEY, -- Delta manifest with a phantom baseline @ baseline INTEGER -- Phantom baseline of this orphan @ ); @ CREATE INDEX orphan_baseline ON orphan(baseline); @ |
︙ | ︙ |
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); } /* |
︙ | ︙ | |||
14028 14029 14030 14031 14032 14033 14034 | " -C DIR, --directory DIR Read/extract files from directory DIR", " -n, --dryrun Show the SQL that would have occurred", " Examples:", " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", " .ar -tf ARCHIVE # List members of ARCHIVE", " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", " See also:", | | | 14813 14814 14815 14816 14817 14818 14819 14820 14821 14822 14823 14824 14825 14826 14827 | " -C DIR, --directory DIR Read/extract files from directory DIR", " -n, --dryrun Show the SQL that would have occurred", " Examples:", " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", " .ar -tf ARCHIVE # List members of ARCHIVE", " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", " See also:", " http://sqlite.org/cli.html#sqlite_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION ".auth ON|OFF Show authorizer callbacks", #endif ".backup ?DB? FILE Backup DB (default \"main\") to FILE", " --append Use the appendvfs", " --async Write to FILE without journal and fsync()", |
︙ | ︙ | |||
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.
︙ | ︙ | |||
224 225 226 227 228 229 230 231 232 233 234 235 236 237 | 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); |
︙ | ︙ |
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-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70" /* ** 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 */ |
︙ | ︙ | |||
16445 16446 16447 16448 16449 16450 16451 16452 16453 16454 16455 16456 16457 16458 | /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ #ifndef SET_FULLSYNC # define SET_FULLSYNC(x,y) #endif /* ** The default size of a disk sector */ #ifndef SQLITE_DEFAULT_SECTOR_SIZE # define SQLITE_DEFAULT_SECTOR_SIZE 4096 #endif | > > > > > > | 16555 16556 16557 16558 16559 16560 16561 16562 16563 16564 16565 16566 16567 16568 16569 16570 16571 16572 16573 16574 | /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ #ifndef SET_FULLSYNC # define SET_FULLSYNC(x,y) #endif /* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h */ #ifndef SQLITE_MAX_PATHLEN # define SQLITE_MAX_PATHLEN FILENAME_MAX #endif /* ** The default size of a disk sector */ #ifndef SQLITE_DEFAULT_SECTOR_SIZE # define SQLITE_DEFAULT_SECTOR_SIZE 4096 #endif |
︙ | ︙ | |||
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 */ | < < < | 17119 17120 17121 17122 17123 17124 17125 17126 17127 17128 17129 17130 17131 17132 17133 | 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 */ | | | 17317 17318 17319 17320 17321 17322 17323 17324 17325 17326 17327 17328 17329 17330 17331 | #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. */ | < < | 17690 17691 17692 17693 17694 17695 17696 17697 17698 17699 17700 17701 17702 17703 17704 | ** 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 | > | 17822 17823 17824 17825 17826 17827 17828 17829 17830 17831 17832 17833 17834 17835 17836 | ** 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. | > | 18188 18189 18190 18191 18192 18193 18194 18195 18196 18197 18198 18199 18200 18201 18202 | ** 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 */ | > | 18461 18462 18463 18464 18465 18466 18467 18468 18469 18470 18471 18472 18473 18474 18475 | ** 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 */ | > | 18535 18536 18537 18538 18539 18540 18541 18542 18543 18544 18545 18546 18547 18548 18549 | 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() */ | | | 18607 18608 18609 18610 18611 18612 18613 18614 18615 18616 18617 18618 18619 18620 18621 | #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 */ | | | 18653 18654 18655 18656 18657 18658 18659 18660 18661 18662 18663 18664 18665 18666 18667 | 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 | > | 18686 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 | #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 |
︙ | ︙ | |||
18683 18684 18685 18686 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 | #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** ** SRT_Union Store results as a key in a temporary index | > | 18799 18800 18801 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 | #define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */ #define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */ #define SF_View 0x0200000 /* SELECT statement is a view */ #define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */ #define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */ #define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */ #define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */ #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result ** Type". ** ** SRT_Union Store results as a key in a temporary index |
︙ | ︙ | |||
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 */ | > > > > > > > > > > > > > > > > | 19328 19329 19330 19331 19332 19333 19334 19335 19336 19337 19338 19339 19340 19341 19342 19343 19344 19345 19346 19347 19348 19349 19350 19351 19352 19353 19354 19355 19356 19357 | /* ** 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 | | > > > > | 19398 19399 19400 19401 19402 19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 19417 19418 19419 19420 19421 19422 19423 19424 19425 | #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 */ | > > > > > > > | 19489 19490 19491 19492 19493 19494 19495 19496 19497 19498 19499 19500 19501 19502 19503 19504 19505 19506 19507 19508 19509 19510 19511 19512 19513 | 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 | > | 19534 19535 19536 19537 19538 19539 19540 19541 19542 19543 19544 19545 19546 19547 19548 | /* ** 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 |
︙ | ︙ | |||
19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 19795 | 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 | > | 19927 19928 19929 19930 19931 19932 19933 19934 19935 19936 19937 19938 19939 19940 19941 | 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 |
︙ | ︙ | |||
20017 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); #endif #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, | > | 20163 20164 20165 20166 20167 20168 20169 20170 20171 20172 20173 20174 20175 20176 20177 | SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p); #if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); #endif #ifndef SQLITE_OMIT_TRIGGER SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, |
︙ | ︙ | |||
20160 20161 20162 20163 20164 20165 20166 | 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 | | | 20307 20308 20309 20310 20311 20312 20313 20314 20315 20316 20317 20318 20319 20320 20321 | 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*); |
︙ | ︙ | |||
20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 20224 | #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 */ | > > > | 20358 20359 20360 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 20371 20372 20373 20374 | #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 */ |
︙ | ︙ | |||
20424 20425 20426 20427 20428 20429 20430 | SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); | | | 20574 20575 20576 20577 20578 20579 20580 20581 20582 20583 20584 20585 20586 20587 20588 | SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8); SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*); SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*); SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*); SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8); #else # define sqlite3CteNew(P,T,E,S) ((void*)0) # define sqlite3CteDelete(D,C) # define sqlite3CteWithAdd(P,W,C) ((void*)0) # define sqlite3WithDelete(x,y) # define sqlite3WithPush(x,y,z) #endif |
︙ | ︙ | |||
20677 20678 20679 20680 20681 20682 20683 | 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, | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 20882 20883 20884 20885 20886 20887 20888 20889 | 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 |
︙ | ︙ | |||
20891 20892 20893 20894 20895 20896 20897 | 0, /* xSqllog */ 0, /* pSqllogArg */ #endif #ifdef SQLITE_VDBE_COVERAGE 0, /* xVdbeBranch */ 0, /* pVbeBranchArg */ #endif | | | 21069 21070 21071 21072 21073 21074 21075 21076 21077 21078 21079 21080 21081 21082 21083 | 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 */ |
︙ | ︙ | |||
21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 21465 21466 21467 | 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 */ }; | > | 21632 21633 21634 21635 21636 21637 21638 21639 21640 21641 21642 21643 21644 21645 21646 | 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 */ }; |
︙ | ︙ | |||
21497 21498 21499 21500 21501 21502 21503 | SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); | | | 21676 21677 21678 21679 21680 21681 21682 21683 21684 21685 21686 21687 21688 21689 21690 | SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*); SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64); #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double); #endif SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*)); |
︙ | ︙ | |||
21542 21543 21544 21545 21546 21547 21548 | #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 | | > | 21721 21722 21723 21724 21725 21726 21727 21728 21729 21730 21731 21732 21733 21734 21735 21736 | #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 *); |
︙ | ︙ | |||
23470 23471 23472 23473 23474 23475 23476 | 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 ); | | | 23650 23651 23652 23653 23654 23655 23656 23657 23658 23659 23660 23661 23662 23663 23664 | 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 ){ |
︙ | ︙ | |||
23493 23494 23495 23496 23497 23498 23499 23500 23501 23502 23503 23504 23505 23506 | ){ DO_OS_MALLOC_TEST(0); zPathOut[0] = 0; return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ return pVfs->xDlOpen(pVfs, zPath); } SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ pVfs->xDlError(pVfs, nByte, zBufOut); } SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ return pVfs->xDlSym(pVfs, pHdle, zSym); | > > | 23673 23674 23675 23676 23677 23678 23679 23680 23681 23682 23683 23684 23685 23686 23687 23688 | ){ DO_OS_MALLOC_TEST(0); zPathOut[0] = 0; return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); } #ifndef SQLITE_OMIT_LOAD_EXTENSION SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ assert( zPath!=0 ); assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */ return pVfs->xDlOpen(pVfs, zPath); } SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ pVfs->xDlError(pVfs, nByte, zBufOut); } SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ return pVfs->xDlSym(pVfs, pHdle, zSym); |
︙ | ︙ | |||
27760 27761 27762 27763 27764 27765 27766 | ** Initialize the memory allocation subsystem. */ SQLITE_PRIVATE int sqlite3MallocInit(void){ int rc; if( sqlite3GlobalConfig.m.xMalloc==0 ){ sqlite3MemSetDefault(); } | < | 27942 27943 27944 27945 27946 27947 27948 27949 27950 27951 27952 27953 27954 27955 | ** 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); |
︙ | ︙ | |||
28459 28460 28461 28462 28463 28464 28465 | #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 */ | | | 28640 28641 28642 28643 28644 28645 28646 28647 28648 28649 28650 28651 28652 28653 28654 | #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 */ |
︙ | ︙ | |||
28525 28526 28527 28528 28529 28530 28531 | { '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 }, | | > > > > > > | 28706 28707 28708 28709 28710 28711 28712 28713 28714 28715 28716 28717 28718 28719 28720 28721 28722 28723 28724 28725 28726 28727 28728 | { '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, }; |
︙ | ︙ | |||
29283 29284 29285 29286 29287 29288 29289 | assert( bArgList==0 ); if( pToken && pToken->n ){ sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); } length = width = 0; break; } | | < < | < < < > > > | | | | | > > > > > | 29470 29471 29472 29473 29474 29475 29476 29477 29478 29479 29480 29481 29482 29483 29484 29485 29486 29487 29488 29489 29490 29491 29492 29493 29494 29495 29496 29497 29498 29499 29500 29501 | 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; } |
︙ | ︙ | |||
29877 29878 29879 29880 29881 29882 29883 | 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); | > | < < < < < < < < | 30067 30068 30069 30070 30071 30072 30073 30074 30075 30076 30077 30078 30079 30080 30081 30082 30083 30084 30085 30086 | 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 ){ |
︙ | ︙ | |||
30455 30456 30457 30458 30459 30460 30461 30462 30463 30464 30465 30466 30467 30468 | 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 ){ | > > > > > > > > | 30638 30639 30640 30641 30642 30643 30644 30645 30646 30647 30648 30649 30650 30651 30652 30653 30654 30655 30656 30657 30658 30659 | 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 ){ |
︙ | ︙ | |||
33529 33530 33531 33532 33533 33534 33535 | /* 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]"), | | | 33720 33721 33722 33723 33724 33725 33726 33727 33728 33729 33730 33731 33732 33733 33734 | /* 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(""), |
︙ | ︙ | |||
33560 33561 33562 33563 33564 33565 33566 | /* 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"), | > | | | | | | | | | | | | < | > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 33846 33847 33848 33849 33850 33851 33852 33853 33854 33855 | /* 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 *****************************************/ |
︙ | ︙ | |||
37808 37809 37810 37811 37812 37813 37814 37815 37816 37817 37818 37819 37820 37821 | }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 ){ | > | 38000 38001 38002 38003 38004 38005 38006 38007 38008 38009 38010 38011 38012 38013 38014 | }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 ){ |
︙ | ︙ | |||
37924 37925 37926 37927 37928 37929 37930 37931 37932 37933 37934 37935 37936 37937 | #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 | > > > > | 38117 38118 38119 38120 38121 38122 38123 38124 38125 38126 38127 38128 38129 38130 38131 38132 38133 38134 | #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 |
︙ | ︙ | |||
38168 38169 38170 38171 38172 38173 38174 38175 38176 38177 38178 38179 38180 38181 | }; /* ** 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 38403 38404 38405 38406 38407 38408 38409 38410 38411 38412 | }; /* ** 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. */ |
︙ | ︙ | |||
41885 41886 41887 41888 41889 41890 41891 41892 41893 41894 41895 41896 41897 41898 | 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, | > > > > > > > > > > > > > > > > | 42116 42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 42128 42129 42130 42131 42132 42133 42134 42135 42136 42137 42138 42139 42140 42141 42142 42143 42144 42145 | 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, |
︙ | ︙ | |||
48278 48279 48280 48281 48282 48283 48284 | ** 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" */ | | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < > > > > > > > > > > > > > > > > > > > > > > | 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 48611 48612 48613 48614 48615 48616 48617 48618 48619 48620 | ** 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); |
︙ | ︙ | |||
48356 48357 48358 48359 48360 48361 48362 | memdbDlError, /* xDlError */ memdbDlSym, /* xDlSym */ memdbDlClose, /* xDlClose */ memdbRandomness, /* xRandomness */ memdbSleep, /* xSleep */ 0, /* memdbCurrentTime, */ /* xCurrentTime */ memdbGetLastError, /* xGetLastError */ | | > > > | 48660 48661 48662 48663 48664 48665 48666 48667 48668 48669 48670 48671 48672 48673 48674 48675 48676 48677 | 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 */ |
︙ | ︙ | |||
48381 48382 48383 48384 48385 48386 48387 48388 48389 48390 48391 | 0, /* xShmLock */ 0, /* xShmBarrier */ 0, /* xShmUnmap */ memdbFetch, /* xFetch */ memdbUnfetch /* xUnfetch */ }; /* ** Close an memdb-file. | > > > > > > > > > > > > > > > > > > > > | < < < | > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > | > > > | | | > | > > > > > > > | > > | > > | > > | > > | > > | > > > > | | < | > > > > > | > > > > > > > > > > > > > > > > > > > | > | | > | > | > > > | > > | > > > > | | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > | > > > | | | 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 49083 49084 49085 49086 49087 49088 49089 49090 49091 49092 | 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, |
︙ | ︙ | |||
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 48660 | */ 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. */ | > > > > | 49106 49107 49108 49109 49110 49111 49112 49113 49114 49115 49116 49117 49118 49119 49120 49121 49122 49123 49124 49125 49126 49127 49128 49129 49130 49131 49132 49133 49134 49135 49136 49137 49138 | */ 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. */ |
︙ | ︙ | |||
48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 48733 48734 48735 | /* ** 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( | > > > > > | 49197 49198 49199 49200 49201 49202 49203 49204 49205 49206 49207 49208 49209 49210 49211 49212 49213 49214 49215 49216 49217 49218 | /* ** 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( |
︙ | ︙ | |||
48757 48758 48759 48760 48761 48762 48763 | 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 ){ | > > | | | | | 49240 49241 49242 49243 49244 49245 49246 49247 49248 49249 49250 49251 49252 49253 49254 49255 49256 49257 49258 49259 49260 49261 | 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); |
︙ | ︙ | |||
48856 48857 48858 48859 48860 48861 48862 | rc = SQLITE_ERROR; goto end_deserialize; } p = memdbFromDbSchema(db, zSchema); if( p==0 ){ rc = SQLITE_ERROR; }else{ | > | | | | | | | | | | 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 49384 49385 49386 49387 49388 49389 49390 49391 49392 49393 | 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 |
︙ | ︙ | |||
56079 56080 56081 56082 56083 56084 56085 | ** ** 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){ | | > | 56565 56566 56567 56568 56569 56570 56571 56572 56573 56574 56575 56576 56577 56578 56579 56580 | ** ** 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 |
︙ | ︙ | |||
56807 56808 56809 56810 56811 56812 56813 | 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 */ | | | 57294 57295 57296 57297 57298 57299 57300 57301 57302 57303 57304 57305 57306 57307 57308 | 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 */ |
︙ | ︙ | |||
57011 57012 57013 57014 57015 57016 57017 | /* 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 ); | | | 57498 57499 57500 57501 57502 57503 57504 57505 57506 57507 57508 57509 57510 57511 57512 | /* 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: |
︙ | ︙ | |||
57979 57980 57981 57982 57983 57984 57985 | 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; | | | 58466 58467 58468 58469 58470 58471 58472 58473 58474 58475 58476 58477 58478 58479 58480 | 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) ){ |
︙ | ︙ | |||
60853 60854 60855 60856 60857 60858 60859 | ** 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[] */ | < | | | 61340 61341 61342 61343 61344 61345 61346 61347 61348 61349 61350 61351 61352 61353 61354 61355 61356 61357 61358 61359 61360 61361 61362 61363 61364 61365 61366 61367 61368 61369 | ** 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++){ |
︙ | ︙ | |||
65499 65500 65501 65502 65503 65504 65505 | 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; | | | 65985 65986 65987 65988 65989 65990 65991 65992 65993 65994 65995 65996 65997 65998 65999 | 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; |
︙ | ︙ | |||
66400 66401 66402 66403 66404 66405 66406 66407 66408 66409 66410 66411 66412 66413 | 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; | > | 66886 66887 66888 66889 66890 66891 66892 66893 66894 66895 66896 66897 66898 66899 66900 | 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; |
︙ | ︙ | |||
66441 66442 66443 66444 66445 66446 66447 | } 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; | | > | | | | < < | | 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 66978 66979 66980 66981 66982 66983 66984 66985 66986 66987 | } 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], usableSize - iCellStart); src = temp; } memcpy(&data[cbrk], &src[pc], size); } data[hdr+7] = 0; defragment_out: |
︙ | ︙ | |||
70346 70347 70348 70349 70350 70351 70352 | #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 ); } | | > > | 70832 70833 70834 70835 70836 70837 70838 70839 70840 70841 70842 70843 70844 70845 70846 70847 70848 | #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); |
︙ | ︙ | |||
71113 71114 71115 71116 71117 71118 71119 | } }else{ closest = 0; } iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); | | | 71601 71602 71603 71604 71605 71606 71607 71608 71609 71610 71611 71612 71613 71614 71615 | } }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)) ){ |
︙ | ︙ | |||
71369 71370 71371 71372 71373 71374 71375 | static void freePage(MemPage *pPage, int *pRC){ if( (*pRC)==SQLITE_OK ){ *pRC = freePage2(pPage->pBt, pPage, pPage->pgno); } } /* | | < | < | < < | 71857 71858 71859 71860 71861 71862 71863 71864 71865 71866 71867 71868 71869 71870 71871 71872 71873 71874 71875 71876 71877 71878 71879 71880 71881 71882 71883 71884 71885 | 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); |
︙ | ︙ | |||
71442 71443 71444 71445 71446 71447 71448 71449 71450 71451 71452 71453 71454 71455 | 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[]. | > > > > > > > > > > > > > > > | 71926 71927 71928 71929 71930 71931 71932 71933 71934 71935 71936 71937 71938 71939 71940 71941 71942 71943 71944 71945 71946 71947 71948 71949 71950 71951 71952 71953 71954 | 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[]. |
︙ | ︙ | |||
71965 71966 71967 71968 71969 71970 71971 | pSrcEnd = pCArray->apEnd[k]; pData = pEnd; while( 1/*exit by break*/ ){ u8 *pCell = pCArray->apCell[i]; u16 sz = pCArray->szCell[i]; assert( sz>0 ); | | | < | 72464 72465 72466 72467 72468 72469 72470 72471 72472 72473 72474 72475 72476 72477 72478 72479 72480 72481 72482 72483 72484 72485 72486 72487 72488 72489 72490 72491 72492 | 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]; } } |
︙ | ︙ | |||
72119 72120 72121 72122 72123 72124 72125 | if( pFree!=(pCell + sz) ){ if( pFree ){ assert( pFree>aData && (pFree - aData)<65536 ); freeSpace(pPg, (u16)(pFree - aData), szFree); } pFree = pCell; szFree = sz; | | > > | 72617 72618 72619 72620 72621 72622 72623 72624 72625 72626 72627 72628 72629 72630 72631 72632 72633 | 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++; } } |
︙ | ︙ | |||
72772 72773 72774 72775 72776 72777 72778 | 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 ); | | | 73272 73273 73274 73275 73276 73277 73278 73279 73280 73281 73282 73283 73284 73285 73286 | 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 |
︙ | ︙ | |||
73095 73096 73097 73098 73099 73100 73101 73102 73103 73104 73105 73106 73107 73108 | } /* 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; | > | 73595 73596 73597 73598 73599 73600 73601 73602 73603 73604 73605 73606 73607 73608 73609 | } /* 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; |
︙ | ︙ | |||
73138 73139 73140 73141 73142 73143 73144 73145 73146 73147 73148 73149 73150 73151 | 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 | > > > > > > | 73639 73640 73641 73642 73643 73644 73645 73646 73647 73648 73649 73650 73651 73652 73653 73654 73655 73656 73657 73658 | 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 |
︙ | ︙ | |||
73680 73681 73682 73683 73684 73685 73686 73687 73688 73689 73690 73691 73692 | ** 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 */ | > > > > > > > > > | > | 74187 74188 74189 74190 74191 74192 74193 74194 74195 74196 74197 74198 74199 74200 74201 74202 74203 74204 74205 74206 74207 74208 74209 74210 74211 74212 74213 74214 74215 74216 74217 | ** 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 ); |
︙ | ︙ | |||
73767 73768 73769 73770 73771 73772 73773 | BtreePayload x2; x2.pData = pX->pKey; x2.nData = pX->nKey; x2.nZero = 0; return btreeOverwriteCell(pCur, &x2); } } | < | | 74284 74285 74286 74287 74288 74289 74290 74291 74292 74293 74294 74295 74296 74297 74298 74299 74300 74301 74302 74303 74304 74305 74306 74307 | 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; } |
︙ | ︙ | |||
73821 73822 73823 73824 73825 73826 73827 | if( rc ){ goto end_insert; } oldCell = findCell(pPage, idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } | | | 74337 74338 74339 74340 74341 74342 74343 74344 74345 74346 74347 74348 74349 74350 74351 | 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 |
︙ | ︙ | |||
74058 74059 74060 74061 74062 74063 74064 | 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); | > | | | 74574 74575 74576 74577 74578 74579 74580 74581 74582 74583 74584 74585 74586 74587 74588 74589 74590 74591 | 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; |
︙ | ︙ | |||
74113 74114 74115 74116 74117 74118 74119 | 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. */ | | | | 74630 74631 74632 74633 74634 74635 74636 74637 74638 74639 74640 74641 74642 74643 74644 74645 74646 74647 74648 74649 74650 74651 74652 74653 | 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 |
︙ | ︙ | |||
74409 74410 74411 74412 74413 74414 74415 | 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; } | | > | < | 74926 74927 74928 74929 74930 74931 74932 74933 74934 74935 74936 74937 74938 74939 74940 74941 74942 74943 74944 74945 74946 74947 | 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); |
︙ | ︙ | |||
74441 74442 74443 74444 74445 74446 74447 | ** 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. ** | | | < > | > | 74958 74959 74960 74961 74962 74963 74964 74965 74966 74967 74968 74969 74970 74971 74972 74973 74974 74975 74976 74977 74978 74979 74980 74981 74982 74983 74984 74985 74986 74987 74988 74989 | ** 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; } /* |
︙ | ︙ | |||
76540 76541 76542 76543 76544 76545 76546 | }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 | > > | | 77058 77059 77060 77061 77062 77063 77064 77065 77066 77067 77068 77069 77070 77071 77072 77073 77074 | }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 |
︙ | ︙ | |||
76704 76705 76706 76707 76708 76709 76710 | /* 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 | > > | | 77224 77225 77226 77227 77228 77229 77230 77231 77232 77233 77234 77235 77236 77237 77238 77239 77240 | /* 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; |
︙ | ︙ | |||
77533 77534 77535 77536 77537 77538 77539 | ** stored without allocating memory, then it is. If a memory allocation ** is required to store the string, then value of pMem is unchanged. In ** either case, SQLITE_TOOBIG is returned. */ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( Mem *pMem, /* Memory cell to set to string value */ const char *z, /* String pointer */ | | | | 78055 78056 78057 78058 78059 78060 78061 78062 78063 78064 78065 78066 78067 78068 78069 78070 78071 78072 78073 | ** stored without allocating memory, then it is. If a memory allocation ** is required to store the string, then value of pMem is unchanged. In ** either case, SQLITE_TOOBIG is returned. */ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( Mem *pMem, /* Memory cell to set to string value */ const char *z, /* String pointer */ i64 n, /* Bytes in string, or negative */ u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ i64 nByte = n; /* New value for pMem->n */ int iLimit; /* Maximum allowed string or blob size */ u16 flags = 0; /* New value for pMem->flags */ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( !sqlite3VdbeMemIsRowSet(pMem) ); /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ |
︙ | ︙ | |||
77559 77560 77561 77562 77563 77564 77565 | }else{ iLimit = SQLITE_MAX_LENGTH; } flags = (enc==0?MEM_Blob:MEM_Str); if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ | | | | 78081 78082 78083 78084 78085 78086 78087 78088 78089 78090 78091 78092 78093 78094 78095 78096 78097 78098 78099 78100 78101 78102 78103 78104 78105 78106 78107 | }else{ iLimit = SQLITE_MAX_LENGTH; } flags = (enc==0?MEM_Blob:MEM_Str); if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ nByte = strlen(z); }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} } flags |= MEM_Term; } /* The following block sets the new values of Mem.z and Mem.xDel. It ** also sets a flag in local variable "flags" to indicate the memory ** management (one of MEM_Dyn or MEM_Static). */ if( xDel==SQLITE_TRANSIENT ){ i64 nAlloc = nByte; if( flags&MEM_Term ){ nAlloc += (enc==SQLITE_UTF8?1:2); } if( nByte>iLimit ){ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); } testcase( nAlloc==0 ); |
︙ | ︙ | |||
77597 77598 77599 77600 77601 77602 77603 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); }else{ pMem->xDel = xDel; flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); } } | | | | 78119 78120 78121 78122 78123 78124 78125 78126 78127 78128 78129 78130 78131 78132 78133 78134 78135 78136 78137 78138 78139 78140 78141 78142 78143 78144 78145 78146 78147 78148 78149 78150 78151 78152 78153 | pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); }else{ pMem->xDel = xDel; flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); } } pMem->n = (int)(nByte & 0x7fffffff); pMem->flags = flags; if( enc ){ pMem->enc = enc; #ifdef SQLITE_ENABLE_SESSION }else if( pMem->db==0 ){ pMem->enc = SQLITE_UTF8; #endif }else{ assert( pMem->db!=0 ); pMem->enc = ENC(pMem->db); } #ifndef SQLITE_OMIT_UTF16 if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM_BKPT; } #endif if( nByte>iLimit ){ return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); } return SQLITE_OK; } /* ** Move data out of a btree key or data field and into a Mem structure. |
︙ | ︙ | |||
79860 79861 79862 79863 79864 79865 79866 | 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 ){ | < < < | < | 80382 80383 80384 80385 80386 80387 80388 80389 80390 80391 80392 80393 80394 80395 80396 | 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); |
︙ | ︙ | |||
83566 83567 83568 83569 83570 83571 83572 | 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 */ | | > | 84084 84085 84086 84087 84088 84089 84090 84091 84092 84093 84094 84095 84096 84097 84098 84099 | 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; |
︙ | ︙ | |||
83602 83603 83604 83605 83606 83607 83608 83609 83610 83611 83612 83613 83614 83615 | 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); | > | 84121 84122 84123 84124 84125 84126 84127 84128 84129 84130 84131 84132 84133 84134 84135 | 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); |
︙ | ︙ | |||
84015 84016 84017 84018 84019 84020 84021 | if( xDel==0 ){ /* noop */ }else if( xDel==SQLITE_TRANSIENT ){ /* noop */ }else{ xDel((void*)p); } | | | 84535 84536 84537 84538 84539 84540 84541 84542 84543 84544 84545 84546 84547 84548 84549 | if( xDel==0 ){ /* noop */ }else if( xDel==SQLITE_TRANSIENT ){ /* noop */ }else{ xDel((void*)p); } sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } SQLITE_API void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, void (*xDel)(void *) |
︙ | ︙ | |||
84997 84998 84999 85000 85001 85002 85003 | /* ** Bind a text or BLOB value. */ static int bindText( sqlite3_stmt *pStmt, /* The statement to bind against */ int i, /* Index of the parameter to bind */ const void *zData, /* Pointer to the data to be bound */ | | | 85517 85518 85519 85520 85521 85522 85523 85524 85525 85526 85527 85528 85529 85530 85531 | /* ** Bind a text or BLOB value. */ static int bindText( sqlite3_stmt *pStmt, /* The statement to bind against */ int i, /* Index of the parameter to bind */ const void *zData, /* Pointer to the data to be bound */ i64 nData, /* Number of bytes of data to be bound */ void (*xDel)(void*), /* Destructor for the data */ u8 encoding /* Encoding for the data */ ){ Vdbe *p = (Vdbe *)pStmt; Mem *pVar; int rc; |
︙ | ︙ | |||
85049 85050 85051 85052 85053 85054 85055 | sqlite3_stmt *pStmt, int i, const void *zData, sqlite3_uint64 nData, void (*xDel)(void*) ){ assert( xDel!=SQLITE_DYNAMIC ); | < < < | < | 85569 85570 85571 85572 85573 85574 85575 85576 85577 85578 85579 85580 85581 85582 85583 | sqlite3_stmt *pStmt, int i, const void *zData, sqlite3_uint64 nData, void (*xDel)(void*) ){ assert( xDel!=SQLITE_DYNAMIC ); return bindText(pStmt, i, zData, nData, xDel, 0); } SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); |
︙ | ︙ | |||
85123 85124 85125 85126 85127 85128 85129 | int i, const char *zData, sqlite3_uint64 nData, void (*xDel)(void*), unsigned char enc ){ assert( xDel!=SQLITE_DYNAMIC ); | < < < | | < | 85639 85640 85641 85642 85643 85644 85645 85646 85647 85648 85649 85650 85651 85652 85653 85654 | int i, const char *zData, sqlite3_uint64 nData, void (*xDel)(void*), unsigned char enc ){ assert( xDel!=SQLITE_DYNAMIC ); if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE; return bindText(pStmt, i, zData, nData, xDel, enc); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API int sqlite3_bind_text16( sqlite3_stmt *pStmt, int i, const void *zData, int nData, |
︙ | ︙ | |||
85527 85528 85529 85530 85531 85532 85533 85534 85535 85536 85537 85538 85539 85540 | ** 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){ | > > > > > > > > > > > | 86039 86040 86041 86042 86043 86044 86045 86046 86047 86048 86049 86050 86051 86052 86053 86054 86055 86056 86057 86058 86059 86060 86061 86062 86063 | ** 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){ |
︙ | ︙ | |||
86149 86150 86151 86152 86153 86154 86155 | (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; } | > | > > > > > > > > > > > > > > > > > > | | | | | | | | | | < | 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 86714 86715 | (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 |
︙ | ︙ | |||
86307 86308 86309 86310 86311 86312 86313 | ** 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 ); | | > > > | 86848 86849 86850 86851 86852 86853 86854 86855 86856 86857 86858 86859 86860 86861 86862 86863 86864 86865 | ** 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; |
︙ | ︙ | |||
86444 86445 86446 86447 86448 86449 86450 86451 86452 86453 86454 86455 86456 86457 | 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. | > > > > > | 86988 86989 86990 86991 86992 86993 86994 86995 86996 86997 86998 86999 87000 87001 87002 87003 87004 87005 87006 | 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. |
︙ | ︙ | |||
87436 87437 87438 87439 87440 87441 87442 | ** 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 ); | | | 87985 87986 87987 87988 87989 87990 87991 87992 87993 87994 87995 87996 87997 87998 87999 | ** 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 |
︙ | ︙ | |||
87878 87879 87880 87881 87882 87883 87884 | } #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 | | < | 88427 88428 88429 88430 88431 88432 88433 88434 88435 88436 88437 88438 88439 88440 88441 | } #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 |
︙ | ︙ | |||
87905 87906 87907 87908 87909 87910 87911 | ** ** 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. ** | | | < < < < < | < | 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 88480 88481 | ** ** 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 |
︙ | ︙ | |||
87948 87949 87950 87951 87952 87953 87954 87955 87956 87957 87958 87959 87960 87961 | ** 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. | > > > | 88490 88491 88492 88493 88494 88495 88496 88497 88498 88499 88500 88501 88502 88503 88504 88505 88506 | ** 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. |
︙ | ︙ | |||
87985 87986 87987 87988 87989 87990 87991 87992 87993 87994 87995 87996 87997 87998 | 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. */ | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 88567 88568 | 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. */ |
︙ | ︙ | |||
88007 88008 88009 88010 88011 88012 88013 | 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. */ | < < | < < < < | | | < | > < < < < < < < < | 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 88611 88612 | 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) ); |
︙ | ︙ | |||
88065 88066 88067 88068 88069 88070 88071 | 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); } | | | < | < | < | > < < < < < < < < < < < < < < < < < < < < < < < < | | | | < | | < | | | | < | < | | | 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 88690 88691 | 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 |
︙ | ︙ | |||
88461 88462 88463 88464 88465 88466 88467 88468 88469 88470 88471 88472 88473 88474 | 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 */ | > > > > > > > > > > > > > > > > > > | 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 89017 89018 | 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 */ |
︙ | ︙ | |||
90518 90519 90520 90521 90522 90523 90524 90525 90526 90527 90528 90529 90530 90531 90532 90533 | 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 | > > > > > > > > > > | 91062 91063 91064 91065 91066 91067 91068 91069 91070 91071 91072 91073 91074 91075 91076 91077 91078 91079 91080 91081 91082 91083 91084 91085 91086 91087 | 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 |
︙ | ︙ | |||
90634 90635 90636 90637 90638 90639 90640 90641 90642 90643 90644 90645 90646 90647 | ** 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 */ | > > > > > | 91188 91189 91190 91191 91192 91193 91194 91195 91196 91197 91198 91199 91200 91201 91202 91203 91204 91205 91206 | ** 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 */ |
︙ | ︙ | |||
91063 91064 91065 91066 91067 91068 91069 | 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) ){ | | | 91622 91623 91624 91625 91626 91627 91628 91629 91630 91631 91632 91633 91634 91635 91636 | 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; |
︙ | ︙ | |||
91223 91224 91225 91226 91227 91228 91229 | 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, | | | 91782 91783 91784 91785 91786 91787 91788 91789 91790 91791 91792 91793 91794 91795 91796 | 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 ); |
︙ | ︙ | |||
92169 92170 92171 92172 92173 92174 92175 | ** 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. ** | | < | | | | < < | 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 92754 92755 92756 | ** 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; } |
︙ | ︙ | |||
92292 92293 92294 92295 92296 92297 92298 | 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 ); | | > > | 92848 92849 92850 92851 92852 92853 92854 92855 92856 92857 92858 92859 92860 92861 92862 92863 92864 | 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 || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) ); #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; |
︙ | ︙ | |||
93174 93175 93176 93177 93178 93179 93180 93181 93182 93183 93184 93185 93186 93187 | 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 | > | 93732 93733 93734 93735 93736 93737 93738 93739 93740 93741 93742 93743 93744 93745 93746 | 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 |
︙ | ︙ | |||
94652 94653 94654 94655 94656 94657 94658 | ** 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( | | | 95211 95212 95213 95214 95215 95216 95217 95218 95219 95220 95221 95222 95223 95224 95225 | ** 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 ){ |
︙ | ︙ | |||
94723 94724 94725 94726 94727 94728 94729 94730 94731 94732 94733 94734 94735 94736 | 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 ); } | > | 95282 95283 95284 95285 95286 95287 95288 95289 95290 95291 95292 95293 95294 95295 95296 | 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 ); } |
︙ | ︙ | |||
98193 98194 98195 98196 98197 98198 98199 | } /* ** Truncate the in-memory file. */ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ MemJournal *p = (MemJournal *)pJfd; | > > | < | | | | | | | | | | | | | | | | | > | 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 98784 98785 98786 98787 98788 | } /* ** 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){ |
︙ | ︙ | |||
98405 98406 98407 98408 98409 98410 98411 | 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; | < < < < < | | | 98967 98968 98969 98970 98971 98972 98973 98974 98975 98976 98977 98978 98979 98980 98981 98982 98983 98984 | 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 /* |
︙ | ︙ | |||
98489 98490 98491 98492 98493 98494 98495 98496 98497 98498 98499 98500 98501 98502 98503 98504 98505 98506 98507 98508 98509 | 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; | > > > > > > > > > > | < > | > | > > > > | 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 99088 99089 99090 99091 99092 | 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 |
︙ | ︙ | |||
98530 98531 98532 98533 98534 98535 98536 | */ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){ SrcList *pSrc; int i; SrcItem *pItem; pSrc = p->pSrc; | | | 99102 99103 99104 99105 99106 99107 99108 99109 99110 99111 99112 99113 99114 99115 99116 | */ 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) ){ |
︙ | ︙ | |||
98704 98705 98706 98707 98708 98709 98710 | 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); | > > | > | 99276 99277 99278 99279 99280 99281 99282 99283 99284 99285 99286 99287 99288 99289 99290 99291 99292 99293 | 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, |
︙ | ︙ | |||
98726 98727 98728 98729 98730 98731 98732 | 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) ){ | | < < | 99301 99302 99303 99304 99305 99306 99307 99308 99309 99310 99311 99312 99313 99314 99315 99316 | 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); } } |
︙ | ︙ | |||
98999 99000 99001 99002 99003 99004 99005 | */ 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 ); | | > | > | 99572 99573 99574 99575 99576 99577 99578 99579 99580 99581 99582 99583 99584 99585 99586 99587 99588 99589 | */ 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 ){ |
︙ | ︙ | |||
99119 99120 99121 99122 99123 99124 99125 | ** ** 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. */ | > | < | 99694 99695 99696 99697 99698 99699 99700 99701 99702 99703 99704 99705 99706 99707 99708 99709 | ** ** 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 |
︙ | ︙ | |||
99184 99185 99186 99187 99188 99189 99190 | ** 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) | < < < < < < | 99759 99760 99761 99762 99763 99764 99765 99766 99767 99768 99769 99770 99771 99772 99773 99774 99775 99776 99777 99778 99779 99780 99781 99782 99783 99784 99785 99786 | ** 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; |
︙ | ︙ | |||
99234 99235 99236 99237 99238 99239 99240 | 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; | | | 99803 99804 99805 99806 99807 99808 99809 99810 99811 99812 99813 99814 99815 99816 99817 | 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. ** |
︙ | ︙ | |||
99541 99542 99543 99544 99545 99546 99547 | 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"); | | | 100110 100111 100112 100113 100114 100115 100116 100117 100118 100119 100120 100121 100122 100123 100124 | 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 |
︙ | ︙ | |||
99563 99564 99565 99566 99567 99568 99569 | #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); | | | 100132 100133 100134 100135 100136 100137 100138 100139 100140 100141 100142 100143 100144 100145 100146 | #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) ){ |
︙ | ︙ | |||
99619 99620 99621 99622 99623 99624 99625 | || (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 ); | | | | | | | | 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 100239 100240 100241 100242 100243 | || (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 |
︙ | ︙ | |||
99884 99885 99886 99887 99888 99889 99890 | /* 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; | | | | | 100453 100454 100455 100456 100457 100458 100459 100460 100461 100462 100463 100464 100465 100466 100467 100468 100469 100470 100471 | /* 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. |
︙ | ︙ | |||
99987 99988 99989 99990 99991 99992 99993 | /* 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. ** | | | < < | | < < < | < > > | < < > | | 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 100583 100584 100585 100586 100587 | /* 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; |
︙ | ︙ | |||
100144 100145 100146 100147 100148 100149 100150 | ){ 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 */ | | | 100708 100709 100710 100711 100712 100713 100714 100715 100716 100717 100718 100719 100720 100721 100722 | ){ 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' ){ |
︙ | ︙ | |||
100234 100235 100236 100237 100238 100239 100240 100241 100242 100243 100244 100245 100246 100247 100248 | 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; | > > | 100798 100799 100800 100801 100802 100803 100804 100805 100806 100807 100808 100809 100810 100811 100812 100813 100814 | 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; |
︙ | ︙ | |||
100309 100310 100311 100312 100313 100314 100315 | 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; } | < < < < < < < > > > > > | > > > > > > > > > > > > > > | 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 100926 100927 100928 100929 100930 | 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; |
︙ | ︙ | |||
100367 100368 100369 100370 100371 100372 100373 | ** 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. */ | > | | 100945 100946 100947 100948 100949 100950 100951 100952 100953 100954 100955 100956 100957 100958 100959 100960 | ** 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; } |
︙ | ︙ | |||
100395 100396 100397 100398 100399 100400 100401 | sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " "the GROUP BY clause"); return WRC_Abort; } } } | < < < < < < < < < < < < < | 100974 100975 100976 100977 100978 100979 100980 100981 100982 100983 100984 100985 100986 100987 | 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; } |
︙ | ︙ | |||
100491 100492 100493 100494 100495 100496 100497 | 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; | | | | 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 101086 101087 101088 101089 101090 | 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. */ |
︙ | ︙ | |||
100555 100556 100557 100558 100559 100560 100561 | 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); } | | | 101121 101122 101123 101124 101125 101126 101127 101128 101129 101130 101131 101132 101133 101134 101135 | 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 |
︙ | ︙ | |||
100698 100699 100700 100701 100702 100703 100704 100705 100706 100707 100708 100709 100710 100711 | 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); } | > > > > < < < < | 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 101290 101291 101292 101293 101294 | 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 ){ |
︙ | ︙ | |||
100741 100742 100743 100744 100745 100746 100747 | */ 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 */ ){ | < < < < < < < < < < < | | 101307 101308 101309 101310 101311 101312 101313 101314 101315 101316 101317 101318 101319 101320 101321 | */ 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; } } |
︙ | ︙ | |||
101102 101103 101104 101105 101106 101107 101108 | ** ** 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){ | | | 101657 101658 101659 101660 101661 101662 101663 101664 101665 101666 101667 101668 101669 101670 101671 | ** ** 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; } |
︙ | ︙ | |||
101218 101219 101220 101221 101222 101223 101224 | 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; | | > | | > > | 101773 101774 101775 101776 101777 101778 101779 101780 101781 101782 101783 101784 101785 101786 101787 101788 101789 101790 101791 101792 101793 101794 101795 101796 101797 101798 101799 101800 | 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. ** |
︙ | ︙ | |||
101257 101258 101259 101260 101261 101262 101263 101264 101265 101266 101267 101268 101269 101270 101271 101272 101273 101274 101275 101276 101277 101278 101279 101280 101281 101282 | 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 ); | > < | | > > | > > | > > > > > > > > > > < < < | < | < < < < > > > > | 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 101896 101897 101898 101899 101900 | 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. |
︙ | ︙ | |||
101960 101961 101962 101963 101964 101965 101966 101967 101968 101969 101970 101971 101972 101973 | 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 ){ | > | 102528 102529 102530 102531 102532 102533 102534 102535 102536 102537 102538 102539 102540 102541 102542 | 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 ){ |
︙ | ︙ | |||
102038 102039 102040 102041 102042 102043 102044 | *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 ); | | > | | | 102607 102608 102609 102610 102611 102612 102613 102614 102615 102616 102617 102618 102619 102620 102621 102622 102623 102624 102625 102626 102627 102628 102629 102630 102631 102632 102633 102634 102635 102636 102637 102638 102639 102640 102641 102642 102643 102644 102645 102646 102647 102648 102649 102650 102651 102652 102653 102654 102655 102656 102657 | *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); } } } return pNew; } /* ** Create and return a deep copy of the object passed as the second ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; for(i=0; i<p->nCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); } } } return pRet; } #else # define sqlite3WithDup(x,y) 0 #endif #ifndef SQLITE_OMIT_WINDOWFUNC /* ** The gatherSelectWindows() procedure and its helper routine ** gatherSelectWindowsCallback() are used to scan all the expressions ** an a newly duplicated SELECT statement and gather all of the Window |
︙ | ︙ | |||
102140 102141 102142 102143 102144 102145 102146 102147 102148 102149 102150 102151 102152 102153 102154 102155 102156 102157 102158 | 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 ){ | > | > | 102710 102711 102712 102713 102714 102715 102716 102717 102718 102719 102720 102721 102722 102723 102724 102725 102726 102727 102728 102729 102730 102731 102732 102733 102734 102735 102736 102737 102738 | 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; |
︙ | ︙ | |||
102275 102276 102277 102278 102279 102280 102281 | pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; | | > > > > > > > > | 102847 102848 102849 102850 102851 102852 102853 102854 102855 102856 102857 102858 102859 102860 102861 102862 102863 102864 102865 102866 102867 102868 102869 102870 102871 102872 102873 102874 102875 | pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags); pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->nSelectRow = p->nSelectRow; pNew->pWith = sqlite3WithDup(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; } |
︙ | ︙ | |||
102312 102313 102314 102315 102316 102317 102318 | ** 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. */ | > | | < | | < | | > | | > | | > > > > > > > > > > | > | | | > > > | > | > > > | > > > > > > > > > > > > < < | < < < < < < | 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 102959 102960 102961 102962 102963 | ** 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) |
︙ | ︙ | |||
102959 102960 102961 102962 102963 102964 102965 102966 102967 102968 102969 102970 102971 102972 102973 102974 | ** 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: | > > | 103562 103563 103564 103565 103566 103567 103568 103569 103570 103571 103572 103573 103574 103575 103576 103577 103578 103579 | ** 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: |
︙ | ︙ | |||
103592 103593 103594 103595 103596 103597 103598 103599 103600 103601 103602 103603 103604 103605 | 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() */ | > > > | > | > < | 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 104223 104224 104225 104226 104227 | 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( |
︙ | ︙ | |||
103703 103704 103705 103706 103707 103708 103709 103710 103711 103712 103713 103714 103715 103716 103717 103718 103719 103720 103721 103722 103723 103724 103725 103726 | 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) ){ | > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < | 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 104356 104357 104358 104359 104360 | 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. ** |
︙ | ︙ | |||
103784 103785 103786 103787 103788 103789 103790 103791 103792 103793 103794 103795 103796 | }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); | > > > > | > | | | | < < | | 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 104434 104435 104436 104437 104438 | }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; |
︙ | ︙ | |||
104001 104002 104003 104004 104005 104006 104007 104008 104009 104010 104011 104012 104013 104014 | 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 | > | 104615 104616 104617 104618 104619 104620 104621 104622 104623 104624 104625 104626 104627 104628 104629 | 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 |
︙ | ︙ | |||
104626 104627 104628 104629 104630 104631 104632 | 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. */ | | | 105241 105242 105243 105244 105245 105246 105247 105248 105249 105250 105251 105252 105253 105254 105255 | 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; |
︙ | ︙ | |||
104692 104693 104694 104695 104696 104697 104698 | 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); | > | < > > > > > > | 105307 105308 105309 105310 105311 105312 105313 105314 105315 105316 105317 105318 105319 105320 105321 105322 105323 105324 105325 105326 105327 105328 105329 105330 105331 105332 105333 105334 105335 | 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: |
︙ | ︙ | |||
104963 104964 104965 104966 104967 104968 104969 | break; } case TK_SELECT_COLUMN: { int n; if( pExpr->pLeft->iTable==0 ){ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); } | | > | 105584 105585 105586 105587 105588 105589 105590 105591 105592 105593 105594 105595 105596 105597 105598 105599 | 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; |
︙ | ︙ | |||
106595 106596 106597 106598 106599 106600 106601 106602 106603 106604 106605 106606 106607 106608 | && 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[] */ | > | 107217 107218 107219 107220 107221 107222 107223 107224 107225 107226 107227 107228 107229 107230 107231 | && 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[] */ |
︙ | ︙ | |||
106795 106796 106797 106798 106799 106800 106801 106802 106803 106804 106805 106806 106807 106808 | ** 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; | > | 107418 107419 107420 107421 107422 107423 107424 107425 107426 107427 107428 107429 107430 107431 107432 | ** 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; |
︙ | ︙ | |||
106818 106819 106820 106821 106822 106823 106824 | ** 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 */ | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > | 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 107496 107497 107498 107499 107500 | ** 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. |
︙ | ︙ | |||
107001 107002 107003 107004 107005 107006 107007 | ** 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 " | | | 107649 107650 107651 107652 107653 107654 107655 107656 107657 107658 107659 107660 107661 107662 107663 | ** 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 |
︙ | ︙ | |||
107359 107360 107361 107362 107363 107364 107365 107366 107367 107368 107369 107370 107371 107372 | 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); | > > > > | 108007 108008 108009 108010 108011 108012 108013 108014 108015 108016 108017 108018 108019 108020 108021 108022 108023 108024 | 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); |
︙ | ︙ | |||
107389 107390 107391 107392 107393 107394 107395 | "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); | | | 108041 108042 108043 108044 108045 108046 108047 108048 108049 108050 108051 108052 108053 108054 108055 | "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; } |
︙ | ︙ | |||
107535 107536 107537 107538 107539 107540 107541 107542 107543 107544 107545 107546 | /* ** Iterate through the Select objects that are part of WITH clauses attached ** to select statement pSelect. */ static void renameWalkWith(Walker *pWalker, Select *pSelect){ With *pWith = pSelect->pWith; if( pWith ){ int i; for(i=0; i<pWith->nCte; i++){ Select *p = pWith->a[i].pSelect; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); | > > > > > > > > > > > > | | | > > > | 108187 108188 108189 108190 108191 108192 108193 108194 108195 108196 108197 108198 108199 108200 108201 108202 108203 108204 108205 108206 108207 108208 108209 108210 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 108222 108223 108224 | /* ** Iterate through the Select objects that are part of WITH clauses attached ** to select statement pSelect. */ static void renameWalkWith(Walker *pWalker, Select *pSelect){ With *pWith = pSelect->pWith; if( pWith ){ Parse *pParse = pWalker->pParse; int i; With *pCopy = 0; assert( pWith->nCte>0 ); if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){ /* Push a copy of the With object onto the with-stack. We use a copy ** here as the original will be expanded and resolved (flags SF_Expanded ** and SF_Resolved) below. And the parser code that uses the with-stack ** fails if the Select objects on it have already been expanded and ** resolved. */ pCopy = sqlite3WithDup(pParse->db, pWith); pCopy = sqlite3WithPush(pParse, pCopy, 1); } for(i=0; i<pWith->nCte; i++){ Select *p = pWith->a[i].pSelect; NameContext sNC; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; if( pCopy ) sqlite3SelectPrep(sNC.pParse, p, &sNC); sqlite3WalkSelect(pWalker, p); sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols); } if( pCopy && pParse->pWith==pCopy ){ pParse->pWith = pCopy->pOuter; } } } /* ** Unmap all tokens in the IdList object passed as the second argument. */ |
︙ | ︙ | |||
107570 107571 107572 107573 107574 107575 107576 | /* ** Walker callback used by sqlite3RenameExprUnmap(). */ static int renameUnmapSelectCb(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int i; if( pParse->nErr ) return WRC_Abort; | > > > | > | 108237 108238 108239 108240 108241 108242 108243 108244 108245 108246 108247 108248 108249 108250 108251 108252 108253 108254 108255 | /* ** 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|SF_CopyCte) ){ testcase( pSelect->selFlags & SF_View ); testcase( pSelect->selFlags & SF_CopyCte ); return WRC_Prune; } if( ALWAYS(p->pEList) ){ ExprList *pList = p->pEList; for(i=0; i<pList->nExpr; i++){ if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){ sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); } } |
︙ | ︙ | |||
107654 107655 107656 107657 107658 107659 107660 | */ static RenameToken *renameTokenFind( Parse *pParse, struct RenameCtx *pCtx, void *pPtr ){ RenameToken **pp; | | > > | 108325 108326 108327 108328 108329 108330 108331 108332 108333 108334 108335 108336 108337 108338 108339 108340 108341 | */ 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; |
︙ | ︙ | |||
107676 107677 107678 107679 107680 107681 107682 | /* ** This is a Walker select callback. It does nothing. It is only required ** because without a dummy callback, sqlite3WalkExpr() and similar do not ** descend into sub-select statements. */ static int renameColumnSelectCb(Walker *pWalker, Select *p){ | > > > | > | 108349 108350 108351 108352 108353 108354 108355 108356 108357 108358 108359 108360 108361 108362 108363 108364 108365 108366 108367 | /* ** This is a Walker select callback. It does nothing. It is only required ** because without a dummy callback, sqlite3WalkExpr() and similar do not ** descend into sub-select statements. */ static int renameColumnSelectCb(Walker *pWalker, Select *p){ if( p->selFlags & (SF_View|SF_CopyCte) ){ testcase( pSelect->selFlags & SF_View ); testcase( pSelect->selFlags & SF_CopyCte ); return WRC_Prune; } renameWalkWith(pWalker, p); return WRC_Continue; } /* ** This is a Walker expression callback. ** |
︙ | ︙ | |||
107813 107814 107815 107816 107817 107818 107819 | ** 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 */ | | < < < < < | 108490 108491 108492 108493 108494 108495 108496 108497 108498 108499 108500 108501 108502 108503 108504 108505 108506 108507 108508 108509 | ** 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; |
︙ | ︙ | |||
107856 107857 107858 107859 107860 107861 107862 | 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; | < | 108528 108529 108530 108531 108532 108533 108534 108535 108536 108537 108538 108539 108540 108541 | 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 |
︙ | ︙ | |||
107880 107881 107882 107883 107884 107885 107886 | 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; | | | > > > | | | | | | | | | | | | | > > > > | > | | > | | < < < < > > > | | | | | | > > > > > > > > > > > > > > > > > | 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 108603 108604 108605 108606 108607 108608 108609 108610 108611 108612 108613 108614 108615 108616 108617 108618 108619 108620 108621 108622 108623 108624 108625 108626 108627 108628 108629 108630 | 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) ); |
︙ | ︙ | |||
108158 108159 108160 108161 108162 108163 108164 | 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 | | | 108854 108855 108856 108857 108858 108859 108860 108861 108862 108863 108864 108865 108866 108867 108868 | 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; |
︙ | ︙ | |||
108187 108188 108189 108190 108191 108192 108193 | }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 ){ | > | | | > | 108883 108884 108885 108886 108887 108888 108889 108890 108891 108892 108893 108894 108895 108896 108897 108898 108899 108900 108901 | }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); } |
︙ | ︙ | |||
108291 108292 108293 108294 108295 108296 108297 | /* ** 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; | | > > > > | | 108989 108990 108991 108992 108993 108994 108995 108996 108997 108998 108999 109000 109001 109002 109003 109004 109005 109006 109007 109008 | /* ** 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|SF_CopyCte) ){ testcase( pSelect->selFlags & SF_View ); testcase( pSelect->selFlags & SF_CopyCte ); 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); |
︙ | ︙ | |||
108362 108363 108364 108365 108366 108367 108368 | sCtx.pTab = sqlite3FindTable(db, zOld, zDb); memset(&sWalker, 0, sizeof(Walker)); sWalker.pParse = &sParse; sWalker.xExprCallback = renameTableExprCb; sWalker.xSelectCallback = renameTableSelectCb; sWalker.u.pRename = &sCtx; | | | 109064 109065 109066 109067 109068 109069 109070 109071 109072 109073 109074 109075 109076 109077 109078 | 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 ){ |
︙ | ︙ | |||
108464 108465 108466 108467 108468 108469 108470 108471 108472 108473 108474 108475 108476 108477 108478 108479 108480 108481 108482 108483 108484 | #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. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > | > | 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 109310 109311 109312 109313 109314 109315 109316 109317 109318 109319 109320 109321 109322 109323 109324 109325 109326 109327 109328 109329 109330 109331 109332 109333 109334 109335 109336 109337 109338 109339 109340 109341 | #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; |
︙ | ︙ | |||
108576 108577 108578 108579 108580 108581 108582 | #ifndef SQLITE_OMIT_AUTHORIZATION sqlite3_xauth xAuth = db->xAuth; db->xAuth = 0; #endif UNUSED_PARAMETER(NotUsed); | | | 109395 109396 109397 109398 109399 109400 109401 109402 109403 109404 109405 109406 109407 109408 109409 | #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; } |
︙ | ︙ | |||
108670 108671 108672 108673 108674 108675 108676 108677 108678 108679 108680 108681 108682 108683 108684 108685 | } /* 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); | > | < > > > > | > > > > > > > | > < > > | 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 109555 109556 109557 109558 109559 109560 109561 109562 109563 109564 109565 109566 109567 109568 109569 109570 109571 109572 109573 109574 109575 109576 109577 109578 109579 109580 109581 109582 109583 109584 109585 109586 | } /* 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 *****************************************/ |
︙ | ︙ | |||
110791 110792 110793 110794 110795 110796 110797 | 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 = ""; | | | 111623 111624 111625 111626 111627 111628 111629 111630 111631 111632 111633 111634 111635 111636 111637 | 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 |
︙ | ︙ | |||
111160 111161 111162 111163 111164 111165 111166 | 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 ){ | > | | | | | | | | > > | 111992 111993 111994 111995 111996 111997 111998 111999 112000 112001 112002 112003 112004 112005 112006 112007 112008 112009 112010 112011 112012 112013 112014 112015 112016 | 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 } |
︙ | ︙ | |||
111207 111208 111209 111210 111211 111212 111213 | 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; | | | 112042 112043 112044 112045 112046 112047 112048 112049 112050 112051 112052 112053 112054 112055 112056 | 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 |
︙ | ︙ | |||
111269 111270 111271 111272 111273 111274 111275 | || sqlite3WalkExpr(&pFix->w, pStep->pWhere) || sqlite3WalkExprList(&pFix->w, pStep->pExprList) || sqlite3FixSrcList(pFix, pStep->pFrom) ){ return 1; } #ifndef SQLITE_OMIT_UPSERT | < > | > | | | | | | > | 112104 112105 112106 112107 112108 112109 112110 112111 112112 112113 112114 112115 112116 112117 112118 112119 112120 112121 112122 112123 112124 112125 112126 112127 | || 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; |
︙ | ︙ | |||
111608 111609 111610 111611 111612 111613 111614 | ** 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(). */ | | < < | 112445 112446 112447 112448 112449 112450 112451 112452 112453 112454 112455 112456 112457 112458 112459 112460 112461 112462 112463 112464 112465 112466 112467 112468 112469 112470 112471 | ** 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; } |
︙ | ︙ | |||
111646 111647 111648 111649 111650 111651 111652 111653 111654 111655 111656 111657 111658 111659 | 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; | > > > > > > > > > > > | 112481 112482 112483 112484 112485 112486 112487 112488 112489 112490 112491 112492 112493 112494 112495 112496 112497 112498 112499 112500 112501 112502 112503 112504 112505 | 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; |
︙ | ︙ | |||
112000 112001 112002 112003 112004 112005 112006 | 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. */ | | | 112846 112847 112848 112849 112850 112851 112852 112853 112854 112855 112856 112857 112858 112859 112860 | 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; } |
︙ | ︙ | |||
112023 112024 112025 112026 112027 112028 112029 112030 112031 112032 112033 112034 112035 112036 | 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. | > > | 112869 112870 112871 112872 112873 112874 112875 112876 112877 112878 112879 112880 112881 112882 112883 112884 | 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. |
︙ | ︙ | |||
112439 112440 112441 112442 112443 112444 112445 | *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); return -1; } }else{ | | | 113287 113288 113289 113290 113291 113292 113293 113294 113295 113296 113297 113298 113299 113300 113301 | *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; } |
︙ | ︙ | |||
112607 112608 112609 112610 112611 112612 112613 112614 112615 112616 112617 112618 112619 112620 | 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 | > > > > > > > > > > > > > > > > > | 113455 113456 113457 113458 113459 113460 113461 113462 113463 113464 113465 113466 113467 113468 113469 113470 113471 113472 113473 113474 113475 113476 113477 113478 113479 113480 113481 113482 113483 113484 113485 | 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 |
︙ | ︙ | |||
112707 112708 112709 112710 112711 112712 112713 112714 112715 112716 112717 112718 112719 112720 | 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; } | > | 113572 113573 113574 113575 113576 113577 113578 113579 113580 113581 113582 113583 113584 113585 113586 | 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; } |
︙ | ︙ | |||
112735 112736 112737 112738 112739 112740 112741 | pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST); #else pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); #endif assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; | < < < < < < < < < < < | 113601 113602 113603 113604 113605 113606 113607 113608 113609 113610 113611 113612 113613 113614 | 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. |
︙ | ︙ | |||
112894 112895 112896 112897 112898 112899 112900 112901 112902 112903 112904 112905 112906 112907 | 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) | > | 113749 113750 113751 113752 113753 113754 113755 113756 113757 113758 113759 113760 113761 113762 113763 | 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) |
︙ | ︙ | |||
113752 113753 113754 113755 113756 113757 113758 | */ 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)); | | > > > | > > > | 114608 114609 114610 114611 114612 114613 114614 114615 114616 114617 114618 114619 114620 114621 114622 114623 114624 114625 114626 114627 114628 114629 114630 114631 114632 114633 114634 114635 114636 114637 | */ 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 ); /* |
︙ | ︙ | |||
113965 113966 113967 113968 113969 113970 113971 | 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; } | < | 114827 114828 114829 114830 114831 114832 114833 114834 114835 114836 114837 114838 114839 114840 | 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; } |
︙ | ︙ | |||
114190 114191 114192 114193 114194 114195 114196 | 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. */ | | | 115051 115052 115053 115054 115055 115056 115057 115058 115059 115060 115061 115062 115063 115064 115065 | 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 ); |
︙ | ︙ | |||
114213 114214 114215 114216 114217 114218 114219 114220 114221 114222 114223 114224 114225 114226 114227 114228 114229 114230 114231 114232 114233 114234 | /* 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; | > > > > > > > > > > > > | 115074 115075 115076 115077 115078 115079 115080 115081 115082 115083 115084 115085 115086 115087 115088 115089 115090 115091 115092 115093 115094 115095 115096 115097 115098 115099 115100 115101 115102 115103 115104 115105 115106 115107 | /* 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; |
︙ | ︙ | |||
114264 114265 114266 114267 114268 114269 114270 114271 114272 114273 114274 114275 114276 114277 | 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 | > > > > > > > > > > | 115137 115138 115139 115140 115141 115142 115143 115144 115145 115146 115147 115148 115149 115150 115151 115152 115153 115154 115155 115156 115157 115158 115159 115160 | 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 |
︙ | ︙ | |||
114740 114741 114742 114743 114744 114745 114746 | 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 ){ | > | > > | 115623 115624 115625 115626 115627 115628 115629 115630 115631 115632 115633 115634 115635 115636 115637 115638 115639 115640 | 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. |
︙ | ︙ | |||
115310 115311 115312 115313 115314 115315 115316 115317 115318 115319 115320 115321 115322 115323 | } 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; | > | 116196 116197 116198 116199 116200 116201 116202 116203 116204 116205 116206 116207 116208 116209 116210 | } 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; |
︙ | ︙ | |||
115790 115791 115792 115793 115794 115795 115796 | ** 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; } | | | 116677 116678 116679 116680 116681 116682 116683 116684 116685 116686 116687 116688 116689 116690 116691 | ** 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) ); |
︙ | ︙ | |||
115825 115826 115827 115828 115829 115830 115831 | 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 ){ | | > | | 116712 116713 116714 116715 116716 116717 116718 116719 116720 116721 116722 116723 116724 116725 116726 116727 116728 116729 116730 116731 116732 116733 116734 116735 116736 116737 116738 116739 116740 116741 116742 116743 116744 116745 116746 116747 116748 116749 | 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); goto exit_drop_index; } iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX; if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } } #endif /* Generate code to remove the index and from the schema table */ |
︙ | ︙ | |||
116139 116140 116141 116142 116143 116144 116145 | /* ** Assign VdbeCursor index numbers to all tables in a SrcList */ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; SrcItem *pItem; | | | | 117027 117028 117029 117030 117031 117032 117033 117034 117035 117036 117037 117038 117039 117040 117041 117042 | /* ** 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); } } |
︙ | ︙ | |||
117865 117866 117867 117868 117869 117870 117871 117872 117873 117874 117875 117876 117877 117878 | 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); | > > > | 118753 118754 118755 118756 118757 118758 118759 118760 118761 118762 118763 118764 118765 118766 118767 118768 118769 | 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); |
︙ | ︙ | |||
118376 118377 118378 118379 118380 118381 118382 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] && pPrior->aiColumn[j]!=XN_EXPR ){ /* This column was already computed by the previous index */ continue; } sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); | > | | | | | | | > | 119267 119268 119269 119270 119271 119272 119273 119274 119275 119276 119277 119278 119279 119280 119281 119282 119283 119284 119285 119286 119287 119288 119289 | && pPrior->aiColumn[j]==pIdx->aiColumn[j] && pPrior->aiColumn[j]!=XN_EXPR ){ /* This column was already computed by the previous index */ continue; } sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, j, regBase+j); if( pIdx->aiColumn[j]>=0 ){ /* If the column affinity is REAL but the number is an integer, then it ** might be stored in the table as an integer (using a compact ** representation) then converted to REAL by an OP_RealAffinity opcode. ** But we are getting ready to store this value back into an index, where ** it should be converted by to INTEGER again. So omit the ** OP_RealAffinity opcode if it is present */ sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity); } } if( regOut ){ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); } sqlite3ReleaseTempRange(pParse, regBase, nCol); return regBase; } |
︙ | ︙ | |||
120477 120478 120479 120480 120481 120482 120483 | v1 = sqlite3_value_double(argv[1]); x = (double(*)(double,double))sqlite3_user_data(context); ans = x(v0, v1); sqlite3_result_double(context, ans); } /* | | < < | 121370 121371 121372 121373 121374 121375 121376 121377 121378 121379 121380 121381 121382 121383 121384 | 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 ); |
︙ | ︙ | |||
122509 122510 122511 122512 122513 122514 122515 | 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) | | | 123400 123401 123402 123403 123404 123405 123406 123407 123408 123409 123410 123411 123412 123413 123414 | 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; } |
︙ | ︙ | |||
122968 122969 122970 122971 122972 122973 122974 | } 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", | | | 123859 123860 123861 123862 123863 123864 123865 123866 123867 123868 123869 123870 123871 123872 123873 | } 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; } } } } |
︙ | ︙ | |||
123096 123097 123098 123099 123100 123101 123102 | 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", | | | 123987 123988 123989 123990 123991 123992 123993 123994 123995 123996 123997 123998 123999 124000 124001 | 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; } |
︙ | ︙ | |||
123399 123400 123401 123402 123403 123404 123405 | 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 { | | > > > > > > > | 124290 124291 124292 124293 124294 124295 124296 124297 124298 124299 124300 124301 124302 124303 124304 124305 124306 124307 124308 124309 124310 124311 124312 124313 124314 124315 124316 124317 124318 124319 124320 124321 124322 124323 124324 124325 124326 124327 124328 124329 124330 | 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); } |
︙ | ︙ | |||
126535 126536 126537 126538 126539 126540 126541 | sqlite3_vfs *pVfs = db->pVfs; void *handle; sqlite3_loadext_entry xInit; char *zErrmsg = 0; const char *zEntry; char *zAltEntry = 0; void **aHandle; | | | 127433 127434 127435 127436 127437 127438 127439 127440 127441 127442 127443 127444 127445 127446 127447 | sqlite3_vfs *pVfs = db->pVfs; void *handle; sqlite3_loadext_entry xInit; char *zErrmsg = 0; const char *zEntry; char *zAltEntry = 0; void **aHandle; u64 nMsg = strlen(zFile); int ii; int rc; /* Shared library endings to try if zFile cannot be loaded as written */ static const char *azEndings[] = { #if SQLITE_OS_WIN "dll" |
︙ | ︙ | |||
126569 126570 126571 126572 126573 126574 126575 126576 126577 126578 126579 126580 126581 126582 126583 126584 | *pzErrMsg = sqlite3_mprintf("not authorized"); } return SQLITE_ERROR; } zEntry = zProc ? zProc : "sqlite3_extension_init"; handle = sqlite3OsDlOpen(pVfs, zFile); #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){ char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]); if( zAltFile==0 ) return SQLITE_NOMEM_BKPT; handle = sqlite3OsDlOpen(pVfs, zAltFile); sqlite3_free(zAltFile); } #endif | > > > > > > | < < < < < < < < < < | 127467 127468 127469 127470 127471 127472 127473 127474 127475 127476 127477 127478 127479 127480 127481 127482 127483 127484 127485 127486 127487 127488 127489 127490 127491 127492 127493 127494 127495 127496 | *pzErrMsg = sqlite3_mprintf("not authorized"); } return SQLITE_ERROR; } zEntry = zProc ? zProc : "sqlite3_extension_init"; /* tag-20210611-1. Some dlopen() implementations will segfault if given ** an oversize filename. Most filesystems have a pathname limit of 4K, ** so limit the extension filename length to about twice that. ** https://sqlite.org/forum/forumpost/08a0d6d9bf */ if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found; handle = sqlite3OsDlOpen(pVfs, zFile); #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){ char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]); if( zAltFile==0 ) return SQLITE_NOMEM_BKPT; handle = sqlite3OsDlOpen(pVfs, zAltFile); sqlite3_free(zAltFile); } #endif if( handle==0 ) goto extension_not_found; xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); /* If no entry point was specified and the default legacy ** entry point name "sqlite3_extension_init" was not found, then ** construct an entry point name "sqlite3_X_init" where the X is ** replaced by the lowercase value of every ASCII alphabetic ** character in the filename after the last "/" upto the first ".", |
︙ | ︙ | |||
126625 126626 126627 126628 126629 126630 126631 | } memcpy(zAltEntry+iEntry, "_init", 6); zEntry = zAltEntry; xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ | | > | | 127519 127520 127521 127522 127523 127524 127525 127526 127527 127528 127529 127530 127531 127532 127533 127534 127535 127536 127537 | } memcpy(zAltEntry+iEntry, "_init", 6); zEntry = zAltEntry; xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); } if( xInit==0 ){ if( pzErrMsg ){ nMsg += strlen(zEntry) + 300; *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ sqlite3_snprintf((int)nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zEntry, zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); } } sqlite3OsDlClose(pVfs, handle); sqlite3_free(zAltEntry); return SQLITE_ERROR; |
︙ | ︙ | |||
126662 126663 126664 126665 126666 126667 126668 126669 126670 126671 126672 126673 126674 126675 | memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); } sqlite3DbFree(db, db->aExtension); db->aExtension = aHandle; db->aExtension[db->nExtension++] = handle; return SQLITE_OK; } SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ){ | > > > > > > > > > > > > > | 127557 127558 127559 127560 127561 127562 127563 127564 127565 127566 127567 127568 127569 127570 127571 127572 127573 127574 127575 127576 127577 127578 127579 127580 127581 127582 127583 | memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension); } sqlite3DbFree(db, db->aExtension); db->aExtension = aHandle; db->aExtension[db->nExtension++] = handle; return SQLITE_OK; extension_not_found: if( pzErrMsg ){ nMsg += 300; *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */ sqlite3_snprintf((int)nMsg, zErrmsg, "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile); sqlite3OsDlError(pVfs, nMsg-1, zErrmsg); } } return SQLITE_ERROR; } SQLITE_API int sqlite3_load_extension( sqlite3 *db, /* Load the extension into this database connection */ const char *zFile, /* Name of the shared library containing extension */ const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ char **pzErrMsg /* Put error message here if not 0 */ ){ |
︙ | ︙ | |||
130221 130222 130223 130224 130225 130226 130227 130228 130229 130230 130231 130232 130233 130234 | 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 ); | > < | 131129 131130 131131 131132 131133 131134 131135 131136 131137 131138 131139 131140 131141 131142 131143 131144 131145 131146 131147 131148 131149 131150 | 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 |
︙ | ︙ | |||
130502 130503 130504 130505 130506 130507 130508 130509 130510 130511 | sqlite3DbFree(db, zSql); #ifndef SQLITE_OMIT_ANALYZE if( rc==SQLITE_OK ){ sqlite3AnalysisLoad(db, iDb); } #endif } if( db->mallocFailed ){ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); | > > | | | | | | > > | | | 131410 131411 131412 131413 131414 131415 131416 131417 131418 131419 131420 131421 131422 131423 131424 131425 131426 131427 131428 131429 131430 131431 131432 131433 131434 131435 131436 131437 131438 131439 | sqlite3DbFree(db, zSql); #ifndef SQLITE_OMIT_ANALYZE if( rc==SQLITE_OK ){ sqlite3AnalysisLoad(db, iDb); } #endif } assert( pDb == &(db->aDb[iDb]) ); if( db->mallocFailed ){ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); pDb = &db->aDb[iDb]; }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 |
︙ | ︙ | |||
130623 130624 130625 130626 130627 130628 130629 130630 130631 130632 130633 130634 130635 130636 | /* 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, | > | 131535 131536 131537 131538 131539 131540 131541 131542 131543 131544 131545 131546 131547 131548 131549 | /* 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, |
︙ | ︙ | |||
130858 130859 130860 130861 130862 130863 130864 130865 130866 130867 130868 130869 130870 130871 | } 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); | > | 131771 131772 131773 131774 131775 131776 131777 131778 131779 131780 131781 131782 131783 131784 131785 | } 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); |
︙ | ︙ | |||
131882 131883 131884 131885 131886 131887 131888 | if( iOffset>0 ){ sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v); VdbeComment((v, "OFFSET")); } } /* | | | | > | > > > > > > > > | > > > > > > > > | > > > > > > > > > > > > > > > > > | > | | > > | > > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 132913 132914 132915 132916 132917 132918 132919 132920 132921 132922 132923 132924 132925 132926 132927 132928 132929 132930 132931 132932 132933 132934 132935 132936 132937 132938 132939 132940 132941 132942 132943 132944 132945 132946 132947 132948 132949 132950 132951 132952 132953 132954 132955 132956 132957 132958 | 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 |
︙ | ︙ | |||
132154 132155 132156 132157 132158 132159 132160 | } /* 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 ){ | | < < < < | < < | | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 133192 133193 133194 133195 133196 133197 133198 133199 133200 133201 133202 133203 133204 133205 133206 133207 133208 133209 133210 | } /* 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 |
︙ | ︙ | |||
132872 132873 132874 132875 132876 132877 132878 | 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. */ | | > > > > > > | 133862 133863 133864 133865 133866 133867 133868 133869 133870 133871 133872 133873 133874 133875 133876 133877 133878 133879 133880 133881 133882 | 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; |
︙ | ︙ | |||
133014 133015 133016 133017 133018 133019 133020 | ** 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. */ | | | 134010 134011 134012 134013 134014 134015 134016 134017 134018 134019 134020 134021 134022 134023 134024 | ** 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; |
︙ | ︙ | |||
133104 133105 133106 133107 133108 133109 133110 | ** 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. ** | | | 134100 134101 134102 134103 134104 134105 134106 134107 134108 134109 134110 134111 134112 134113 134114 | ** 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 */ ){ |
︙ | ︙ | |||
133802 133803 133804 133805 133806 133807 133808 | #endif /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; | | > > | 134798 134799 134800 134801 134802 134803 134804 134805 134806 134807 134808 134809 134810 134811 134812 134813 134814 134815 134816 134817 134818 134819 134820 134821 134822 134823 134824 134825 134826 134827 134828 134829 134830 134831 134832 134833 134834 134835 | #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) |
︙ | ︙ | |||
133876 133877 133878 133879 133880 133881 133882 133883 133884 133885 133886 133887 133888 133889 133890 133891 133892 133893 133894 133895 133896 133897 133898 133899 133900 133901 133902 133903 133904 133905 133906 133907 133908 | } /* 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 ){ | > > | 134874 134875 134876 134877 134878 134879 134880 134881 134882 134883 134884 134885 134886 134887 134888 134889 134890 134891 134892 134893 134894 134895 134896 134897 134898 134899 134900 134901 134902 134903 134904 134905 134906 134907 134908 | } /* 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 ){ |
︙ | ︙ | |||
133955 133956 133957 133958 133959 133960 133961 133962 133963 133964 133965 133966 133967 133968 133969 133970 133971 133972 133973 133974 133975 133976 133977 133978 133979 133980 133981 133982 133983 133984 | 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; } | > > | 134955 134956 134957 134958 134959 134960 134961 134962 134963 134964 134965 134966 134967 134968 134969 134970 134971 134972 134973 134974 134975 134976 134977 134978 134979 134980 134981 134982 134983 134984 134985 134986 | 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; } |
︙ | ︙ | |||
134603 134604 134605 134606 134607 134608 134609 134610 134611 134612 134613 134614 134615 134616 | /* 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 | > > > | 135605 135606 135607 135608 135609 135610 135611 135612 135613 135614 135615 135616 135617 135618 135619 135620 135621 | /* 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 |
︙ | ︙ | |||
134658 134659 134660 134661 134662 134663 134664 134665 134666 | ){ 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; | > | > > > > > > | | < | | | | | | | < | 135663 135664 135665 135666 135667 135668 135669 135670 135671 135672 135673 135674 135675 135676 135677 135678 135679 135680 135681 135682 135683 135684 135685 135686 135687 135688 135689 135690 135691 135692 135693 135694 135695 135696 135697 135698 135699 135700 135701 135702 135703 135704 135705 135706 135707 135708 135709 135710 135711 135712 135713 135714 135715 135716 135717 135718 135719 135720 135721 135722 135723 | ){ 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); |
︙ | ︙ | |||
134818 134819 134820 134821 134822 134823 134824 | 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; | > > > | | 135828 135829 135830 135831 135832 135833 135834 135835 135836 135837 135838 135839 135840 135841 135842 135843 135844 135845 | 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); } } } } |
︙ | ︙ | |||
135258 135259 135260 135261 135262 135263 135264 | p->pOrderBy = pOrderBy; p->op = TK_ALL; pSubitem->pTab = pItemTab; if( pNew==0 ){ p->pPrior = pPrior; }else{ pNew->selId = ++pParse->nSelect; | | | 136271 136272 136273 136274 136275 136276 136277 136278 136279 136280 136281 136282 136283 136284 136285 | 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" |
︙ | ︙ | |||
135457 135458 135459 135460 135461 135462 135463 135464 135465 135466 135467 135468 135469 135470 135471 135472 | /* ** A structure to keep track of all of the column values that are fixed to ** 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. ** | > > | 136470 136471 136472 136473 136474 136475 136476 136477 136478 136479 136480 136481 136482 136483 136484 136485 136486 136487 | /* ** A structure to keep track of all of the column values that are fixed to ** a known value due to WHERE clause constraints of the form COLUMN=VALUE. */ typedef struct WhereConst WhereConst; struct WhereConst { Parse *pParse; /* Parsing context */ u8 *pOomFault; /* Pointer to pParse->db->mallocFailed */ 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. ** |
︙ | ︙ | |||
135497 135498 135499 135500 135501 135502 135503 135504 135505 135506 135507 135508 135509 135510 135511 135512 135513 135514 135515 135516 135517 135518 135519 135520 135521 135522 135523 | 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; | > > > | | > | | | > > | > > > > | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 136596 136597 136598 136599 136600 136601 136602 136603 136604 136605 136606 136607 136608 136609 136610 136611 136612 136613 136614 136615 136616 136617 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 | 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( pConst->pOomFault[0] ) return WRC_Prune; 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); if( pConst->pParse->db->mallocFailed ) return WRC_Prune; 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( pConst->pOomFault[0] ) return WRC_Prune; 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 |
︙ | ︙ | |||
135604 135605 135606 135607 135608 135609 135610 135611 135612 135613 135614 135615 135616 135617 135618 135619 135620 135621 135622 135623 135624 135625 135626 135627 135628 135629 135630 | ** 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; | > > > > > > > > > > > > > > > > > | 136668 136669 136670 136671 136672 136673 136674 136675 136676 136677 136678 136679 136680 136681 136682 136683 136684 136685 136686 136687 136688 136689 136690 136691 136692 136693 136694 136695 136696 136697 136698 136699 136700 136701 136702 136703 136704 136705 136706 136707 136708 136709 136710 136711 | ** 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; x.pOomFault = &pParse->db->mallocFailed; 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; |
︙ | ︙ | |||
136053 136054 136055 136056 136057 136058 136059 136060 136061 136062 136063 136064 136065 136066 136067 136068 | 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 | > | | > > > > > > > | < < < | | | > > | > > > > | 137134 137135 137136 137137 137138 137139 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 137172 137173 137174 137175 137176 137177 137178 137179 137180 137181 137182 137183 137184 | 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. ** ** This routine returns a copy of pWith. Or, if bFree is true and ** the pWith object is destroyed immediately due to an OOM condition, ** then this routine return NULL. ** ** If bFree is true, do not continue to use the pWith pointer after ** calling this routine, Instead, use only the return value. */ SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ if( pWith ){ if( bFree ){ pWith = (With*)sqlite3ParserAddCleanup(pParse, (void(*)(sqlite3*,void*))sqlite3WithDelete, pWith); if( pWith==0 ) return 0; } if( pParse->nErr==0 ){ assert( pParse->pWith!=pWith ); pWith->pOuter = pParse->pWith; pParse->pWith = pWith; } } return pWith; } /* ** This function checks if argument pFrom refers to a CTE declared by ** a WITH clause on the stack currently maintained by the parser (on the ** pParse->pWith linked list). And if currently processing a CTE ** CTE expression, through routine checks to see if the reference is |
︙ | ︙ | |||
136107 136108 136109 136110 136111 136112 136113 136114 136115 136116 136117 136118 136119 136120 136121 136122 136123 136124 136125 | 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; | > > > > > > > > > > > > > | 137199 137200 137201 137202 137203 137204 137205 137206 137207 137208 137209 137210 137211 137212 137213 137214 137215 137216 137217 137218 137219 137220 137221 137222 137223 137224 137225 137226 137227 137228 137229 137230 | 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; |
︙ | ︙ | |||
136158 136159 136160 136161 136162 136163 136164 136165 136166 136167 136168 136169 136170 136171 | pTab->nTabRef = 1; pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( db->mallocFailed ) return 2; assert( pFrom->pSelect ); pFrom->fg.isCte = 1; pFrom->u2.pCteUse = pCteUse; pCteUse->nUse++; if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){ pCteUse->eM10d = M10d_Yes; } | > | 137263 137264 137265 137266 137267 137268 137269 137270 137271 137272 137273 137274 137275 137276 137277 | pTab->nTabRef = 1; pTab->zName = sqlite3DbStrDup(db, pCte->zName); pTab->iPKey = -1; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( db->mallocFailed ) return 2; pFrom->pSelect->selFlags |= SF_CopyCte; assert( pFrom->pSelect ); pFrom->fg.isCte = 1; pFrom->u2.pCteUse = pCteUse; pCteUse->nUse++; if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){ pCteUse->eM10d = M10d_Yes; } |
︙ | ︙ | |||
136261 136262 136263 136264 136265 136266 136267 | ** 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. */ | | < < | 137367 137368 137369 137370 137371 137372 137373 137374 137375 137376 137377 137378 137379 137380 137381 137382 137383 137384 137385 137386 137387 137388 137389 137390 | ** 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, |
︙ | ︙ | |||
136299 136300 136301 136302 136303 136304 136305 | }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) ); | > > | > > > > | 137403 137404 137405 137406 137407 137408 137409 137410 137411 137412 137413 137414 137415 137416 137417 137418 137419 137420 137421 137422 137423 | }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: |
︙ | ︙ | |||
136353 136354 136355 136356 136357 136358 136359 136360 136361 136362 136363 136364 136365 136366 | } 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); | > > > > > > > > > | 137463 137464 137465 137466 137467 137468 137469 137470 137471 137472 137473 137474 137475 137476 137477 137478 137479 137480 137481 137482 137483 137484 137485 | } 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); |
︙ | ︙ | |||
136413 136414 136415 136416 136417 136418 136419 136420 136421 136422 136423 136424 136425 136426 | && (db->flags & SQLITE_EnableView)==0 && pTab->pSchema!=db->aDb[1].pSchema ){ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", pTab->zName); } #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTab) && pFrom->fg.fromDDL && ALWAYS(pTab->pVTable!=0) && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) ){ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", pTab->zName); | > | 137532 137533 137534 137535 137536 137537 137538 137539 137540 137541 137542 137543 137544 137545 137546 | && (db->flags & SQLITE_EnableView)==0 && pTab->pSchema!=db->aDb[1].pSchema ){ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", pTab->zName); } #ifndef SQLITE_OMIT_VIRTUALTABLE assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 ); if( IsVirtual(pTab) && pFrom->fg.fromDDL && ALWAYS(pTab->pVTable!=0) && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0) ){ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"", pTab->zName); |
︙ | ︙ | |||
136653 136654 136655 136656 136657 136658 136659 | w.pParse = pParse; if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){ w.xSelectCallback = convertCompoundSelectToSubquery; w.xSelectCallback2 = 0; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; | | | 137773 137774 137775 137776 137777 137778 137779 137780 137781 137782 137783 137784 137785 137786 137787 | 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 /* |
︙ | ︙ | |||
136786 136787 136788 136789 136790 136791 136792 | 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); | | | > > | 137906 137907 137908 137909 137910 137911 137912 137913 137914 137915 137916 137917 137918 137919 137920 137921 137922 137923 | 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 |
︙ | ︙ | |||
136819 136820 136821 136822 136823 136824 136825 | ** 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. */ | | > > > > > | 137941 137942 137943 137944 137945 137946 137947 137948 137949 137950 137951 137952 137953 137954 137955 137956 137957 137958 137959 137960 | ** 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; |
︙ | ︙ | |||
136865 136866 136867 136868 136869 136870 136871 | nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; } | | | < | | 137992 137993 137994 137995 137996 137997 137998 137999 138000 138001 138002 138003 138004 138005 138006 138007 138008 138009 138010 138011 | 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++){ |
︙ | ︙ | |||
136923 136924 136925 136926 136927 136928 136929 | 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))); | | | 138049 138050 138051 138052 138053 138054 138055 138056 138057 138058 138059 138060 138061 138062 138063 | 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 |
︙ | ︙ | |||
137234 137235 137236 137237 137238 137239 137240 | ); goto select_end; } } } if( pDest->eDest==SRT_Output ){ | | | < | 138360 138361 138362 138363 138364 138365 138366 138367 138368 138369 138370 138371 138372 138373 138374 138375 138376 138377 138378 | ); 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); |
︙ | ︙ | |||
137365 137366 137367 137368 137369 137370 137371 | #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(). */ | | > | 138490 138491 138492 138493 138494 138495 138496 138497 138498 138499 138500 138501 138502 138503 138504 138505 | #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); |
︙ | ︙ | |||
137428 137429 137430 137431 137432 137433 137434 | #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; | | < < < < < < < < < < < | | 138554 138555 138556 138557 138558 138559 138560 138561 138562 138563 138564 138565 138566 138567 138568 138569 | #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. |
︙ | ︙ | |||
137496 137497 137498 137499 137500 137501 137502 | /* 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); | | | | 138611 138612 138613 138614 138615 138616 138617 138618 138619 138620 138621 138622 138623 138624 138625 138626 138627 138628 | /* 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); |
︙ | ︙ | |||
137527 137528 137529 137530 137531 137532 137533 | ** 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{ | | < | | | | | 138642 138643 138644 138645 138646 138647 138648 138649 138650 138651 138652 138653 138654 138655 138656 138657 138658 138659 138660 138661 138662 138663 138664 138665 138666 138667 138668 138669 138670 138671 138672 138673 138674 138675 138676 138677 138678 138679 138680 138681 | ** 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; |
︙ | ︙ | |||
137903 137904 137905 137906 137907 137908 137909 137910 137911 137912 137913 137914 137915 137916 | 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++; | > > > > > > > > > > > > > > | 139017 139018 139019 139020 139021 139022 139023 139024 139025 139026 139027 139028 139029 139030 139031 139032 139033 139034 139035 139036 139037 139038 139039 139040 139041 139042 139043 139044 | 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++; |
︙ | ︙ | |||
137939 137940 137941 137942 137943 137944 137945 | /* 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")); | | | | > > > > | 139067 139068 139069 139070 139071 139072 139073 139074 139075 139076 139077 139078 139079 139080 139081 139082 139083 139084 139085 139086 139087 139088 | /* 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; |
︙ | ︙ | |||
138060 138061 138062 138063 138064 138065 138066 | 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); | | > | 139192 139193 139194 139195 139196 139197 139198 139199 139200 139201 139202 139203 139204 139205 139206 139207 139208 139209 139210 139211 139212 139213 139214 139215 139216 139217 139218 139219 139220 | 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 |
︙ | ︙ | |||
138117 138118 138119 138120 138121 138122 138123 138124 138125 138126 138127 138128 138129 138130 | */ 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: ** | > > > > | 139250 139251 139252 139253 139254 139255 139256 139257 139258 139259 139260 139261 139262 139263 139264 139265 139266 139267 | */ 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: ** |
︙ | ︙ | |||
138180 138181 138182 138183 138184 138185 138186 138187 138188 138189 138190 138191 138192 138193 | 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 | > > > | 139317 139318 139319 139320 139321 139322 139323 139324 139325 139326 139327 139328 139329 139330 139331 139332 139333 | 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 |
︙ | ︙ | |||
138203 138204 138205 138206 138207 138208 138209 138210 138211 138212 138213 138214 138215 138216 138217 138218 138219 138220 138221 138222 138223 138224 138225 138226 138227 138228 | 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, | > > > | > | > > > > > | 139343 139344 139345 139346 139347 139348 139349 139350 139351 139352 139353 139354 139355 139356 139357 139358 139359 139360 139361 139362 139363 139364 139365 139366 139367 139368 139369 139370 139371 139372 139373 139374 139375 139376 139377 139378 139379 139380 139381 139382 139383 139384 139385 139386 139387 139388 139389 139390 | 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); |
︙ | ︙ | |||
138272 138273 138274 138275 138276 138277 138278 138279 138280 138281 138282 138283 138284 138285 | ** 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 ); | > > | 139421 139422 139423 139424 139425 139426 139427 139428 139429 139430 139431 139432 139433 139434 139435 139436 | ** 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 ); |
︙ | ︙ | |||
138562 138563 138564 138565 138566 138567 138568 | HashElem *p; /* Loop variable for TEMP triggers */ if( pParse->disableTriggers ){ return 0; } pTmpSchema = pParse->db->aDb[1].pSchema; p = sqliteHashFirst(&pTmpSchema->trigHash); | < < < < | | | > | > | | | | > > > > | | | | | | | | | > > > > > > | > > > > | 139713 139714 139715 139716 139717 139718 139719 139720 139721 139722 139723 139724 139725 139726 139727 139728 139729 139730 139731 139732 139733 139734 139735 139736 139737 139738 139739 139740 139741 139742 139743 139744 139745 139746 139747 139748 139749 139750 139751 139752 139753 139754 139755 139756 139757 139758 139759 139760 139761 | 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 |
︙ | ︙ | |||
138714 138715 138716 138717 138718 138719 138720 | } /* 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", | | | | 139877 139878 139879 139880 139881 139882 139883 139884 139885 139886 139887 139888 139889 139890 139891 139892 139893 139894 139895 139896 | } /* 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; |
︙ | ︙ | |||
139116 139117 139118 139119 139120 139121 139122 | 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 ){ | | | 140279 140280 140281 140282 140283 140284 140285 140286 140287 140288 140289 140290 140291 140292 140293 | 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); |
︙ | ︙ | |||
139388 139389 139390 139391 139392 139393 139394 | 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; } } } | < < < < < < < < < > > > > > > > > > > > > > > > | | | 140551 140552 140553 140554 140555 140556 140557 140558 140559 140560 140561 140562 140563 140564 140565 140566 140567 140568 140569 140570 140571 140572 140573 140574 140575 140576 140577 140578 140579 140580 140581 140582 140583 140584 140585 140586 140587 140588 140589 140590 140591 140592 140593 140594 140595 140596 140597 140598 140599 140600 140601 140602 140603 140604 140605 140606 140607 140608 140609 140610 140611 140612 140613 140614 140615 140616 140617 140618 140619 140620 140621 140622 140623 140624 140625 140626 140627 140628 | 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; } } |
︙ | ︙ | |||
139648 139649 139650 139651 139652 139653 139654 | #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); | > | < | 140817 140818 140819 140820 140821 140822 140823 140824 140825 140826 140827 140828 140829 140830 140831 140832 | #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); } |
︙ | ︙ | |||
140128 140129 140130 140131 140132 140133 140134 140135 140136 140137 140138 140139 140140 140141 | #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]); | > | 141297 141298 141299 141300 141301 141302 141303 141304 141305 141306 141307 141308 141309 141310 141311 | #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]); |
︙ | ︙ | |||
140157 140158 140159 140160 140161 140162 140163 | 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 } | > | | 141327 141328 141329 141330 141331 141332 141333 141334 141335 141336 141337 141338 141339 141340 141341 141342 | 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, |
︙ | ︙ | |||
140707 140708 140709 140710 140711 140712 140713 | if( addrOnce ){ sqlite3VdbeJumpHereOrPopInst(v, addrOnce); } } /* Top of the update loop */ if( eOnePass!=ONEPASS_OFF ){ | > | > > > > | 141878 141879 141880 141881 141882 141883 141884 141885 141886 141887 141888 141889 141890 141891 141892 141893 141894 141895 141896 141897 | 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); } |
︙ | ︙ | |||
143178 143179 143180 143181 143182 143183 143184 143185 143186 143187 143188 143189 143190 143191 | 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); | > | 144354 144355 144356 144357 144358 144359 144360 144361 144362 144363 144364 144365 144366 144367 144368 | 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); |
︙ | ︙ | |||
143594 143595 143596 143597 143598 143599 143600 | */ 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 */ | | | | 144771 144772 144773 144774 144775 144776 144777 144778 144779 144780 144781 144782 144783 144784 144785 144786 | */ 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 */ }; /* |
︙ | ︙ | |||
143904 143905 143906 143907 143908 143909 143910 143911 143912 143913 143914 143915 143916 143917 | #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 | > | 145081 145082 145083 145084 145085 145086 145087 145088 145089 145090 145091 145092 145093 145094 145095 | #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 |
︙ | ︙ | |||
144038 144039 144040 144041 144042 144043 144044 | 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); | < < < < < < | < | < | 145216 145217 145218 145219 145220 145221 145222 145223 145224 145225 145226 145227 145228 145229 145230 145231 | 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) ); |
︙ | ︙ | |||
144195 144196 144197 144198 144199 144200 144201 144202 144203 144204 144205 144206 144207 144208 | && (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++; } | > > > > > > | 145365 145366 145367 145368 145369 145370 145371 145372 145373 145374 145375 145376 145377 145378 145379 145380 145381 145382 145383 145384 | && (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++; } |
︙ | ︙ | |||
144512 144513 144514 144515 144516 144517 144518 | } }else{ pLevel->u.in.nIn = 0; } sqlite3DbFree(pParse->db, aiMap); #endif } | > > > > > > > > > > > > > | > > | 145688 145689 145690 145691 145692 145693 145694 145695 145696 145697 145698 145699 145700 145701 145702 145703 145704 145705 145706 145707 145708 145709 145710 145711 145712 145713 145714 145715 145716 145717 | } }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. ** |
︙ | ︙ | |||
144598 144599 144600 144601 144602 144603 144604 144605 144606 144607 144608 144609 144610 144611 | 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); | > | 145789 145790 145791 145792 145793 145794 145795 145796 145797 145798 145799 145800 145801 145802 145803 | 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); |
︙ | ︙ | |||
144632 144633 144634 144635 144636 144637 144638 | 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{ | | | | 145824 145825 145826 145827 145828 145829 145830 145831 145832 145833 145834 145835 145836 145837 145838 145839 145840 145841 145842 145843 145844 145845 145846 145847 145848 145849 145850 145851 145852 145853 145854 145855 | 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; } } |
︙ | ︙ | |||
144998 144999 145000 145001 145002 145003 145004 | ExprList *pList = p->x.pList; assert( nReg<=pList->nExpr ); for(i=0; i<nReg; i++){ sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i); } } }else{ | | | 146190 146191 146192 146193 146194 146195 146196 146197 146198 146199 146200 146201 146202 146203 146204 | 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. |
︙ | ︙ | |||
145625 145626 145627 145628 145629 145630 145631 | 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). */ | | < < | 146817 146818 146819 146820 146821 146822 146823 146824 146825 146826 146827 146828 146829 146830 146831 | 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 |
︙ | ︙ | |||
146048 146049 146050 146051 146052 146053 146054 | 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 | | > > > > > > | 147238 147239 147240 147241 147242 147243 147244 147245 147246 147247 147248 147249 147250 147251 147252 147253 147254 147255 147256 147257 147258 147259 147260 147261 147262 147263 147264 147265 147266 147267 147268 147269 147270 147271 147272 147273 147274 147275 147276 147277 | 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")); |
︙ | ︙ | |||
146182 146183 146184 146185 146186 146187 146188 146189 146190 146191 146192 146193 146194 146195 | 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; | > | 147378 147379 147380 147381 147382 147383 147384 147385 147386 147387 147388 147389 147390 147391 147392 | 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; |
︙ | ︙ | |||
146346 146347 146348 146349 146350 146351 146352 146353 146354 146355 146356 146357 146358 146359 | 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); | > | 147543 147544 147545 147546 147547 147548 147549 147550 147551 147552 147553 147554 147555 147556 147557 | 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); |
︙ | ︙ | |||
146898 146899 146900 146901 146902 146903 146904 146905 146906 146907 146908 146909 146910 146911 | ){ 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; | > | 148096 148097 148098 148099 148100 148101 148102 148103 148104 148105 148106 148107 148108 148109 148110 | ){ 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; |
︙ | ︙ | |||
147258 147259 147260 147261 147262 147263 147264 | 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); | | | 148457 148458 148459 148460 148461 148462 148463 148464 148465 148466 148467 148468 148469 148470 148471 | 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); } } } } |
︙ | ︙ | |||
147382 147383 147384 147385 147386 147387 147388 147389 147390 147391 147392 147393 147394 147395 147396 147397 147398 147399 147400 | ** 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); } | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 148581 148582 148583 148584 148585 148586 148587 148588 148589 148590 148591 148592 148593 148594 148595 148596 148597 148598 148599 148600 148601 148602 148603 148604 148605 148606 148607 | ** 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. ** |
︙ | ︙ | |||
147763 147764 147765 147766 147767 147768 147769 147770 147771 147772 147773 147774 147775 147776 | 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; | > | 148693 148694 148695 148696 148697 148698 148699 148700 148701 148702 148703 148704 148705 148706 148707 | 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; |
︙ | ︙ | |||
147855 147856 147857 147858 147859 147860 147861 | */ else if( pExpr->op==TK_OR ){ assert( pWC->op==TK_AND ); exprAnalyzeOrTerm(pSrc, pWC, idxTerm); pTerm = &pWC->a[idxTerm]; } #endif /* SQLITE_OMIT_OR_OPTIMIZATION */ | < < < < < < < < < < | 148786 148787 148788 148789 148790 148791 148792 148793 148794 148795 148796 148797 148798 148799 | */ 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 ){ |
︙ | ︙ | |||
148551 148552 148553 148554 148555 148556 148557 | /* ** 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); | | > > | 149472 149473 149474 149475 149476 149477 149478 149479 149480 149481 149482 149483 149484 149485 149486 149487 149488 | /* ** 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. |
︙ | ︙ | |||
148626 148627 148628 148629 148630 148631 148632 148633 148634 148635 148636 148637 148638 148639 | && 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 ); | > > > > > > > > > > > > | 149549 149550 149551 149552 149553 149554 149555 149556 149557 149558 149559 149560 149561 149562 149563 149564 149565 149566 149567 149568 149569 149570 149571 149572 149573 149574 | && 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 ); |
︙ | ︙ | |||
148782 148783 148784 148785 148786 148787 148788 | ){ 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) | | | 149717 149718 149719 149720 149721 149722 149723 149724 149725 149726 149727 149728 149729 149730 149731 | ){ 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; } |
︙ | ︙ | |||
148847 148848 148849 148850 148851 148852 148853 | /* 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; | > | > | 149782 149783 149784 149785 149786 149787 149788 149789 149790 149791 149792 149793 149794 149795 149796 149797 149798 149799 149800 149801 149802 149803 149804 149805 149806 149807 149808 149809 149810 149811 149812 149813 149814 149815 | /* 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 ){ |
︙ | ︙ | |||
148919 148920 148921 148922 148923 148924 148925 | 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 ){ | < | | < > > < > | 149856 149857 149858 149859 149860 149861 149862 149863 149864 149865 149866 149867 149868 149869 149870 149871 149872 149873 149874 149875 149876 149877 | 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 |
︙ | ︙ | |||
149091 149092 149093 149094 149095 149096 149097 | goto end_auto_index_create; } pLoop->aLTerm[nKeyCol++] = pTerm; idxCols |= cMask; } } } | | | 150028 150029 150030 150031 150032 150033 150034 150035 150036 150037 150038 150039 150040 150041 150042 | 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 |
︙ | ︙ | |||
150228 150229 150230 150231 150232 150233 150234 | /* ** 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) ){ | | | 151165 151166 151167 151168 151169 151170 151171 151172 151173 151174 151175 151176 151177 151178 151179 | /* ** 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 ){ |
︙ | ︙ | |||
150270 150271 150272 150273 150274 150275 150276 150277 150278 150279 150280 150281 150282 150283 | 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 | > > > > > > > > > > > | 151207 151208 151209 151210 151211 151212 151213 151214 151215 151216 151217 151218 151219 151220 151221 151222 151223 151224 151225 151226 151227 151228 151229 151230 151231 | 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 |
︙ | ︙ | |||
150776 150777 150778 150779 150780 150781 150782 150783 150784 150785 150786 150787 150788 150789 | }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; | > > | 151724 151725 151726 151727 151728 151729 151730 151731 151732 151733 151734 151735 151736 151737 151738 151739 | }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; |
︙ | ︙ | |||
150858 150859 150860 150861 150862 150863 150864 | 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 ){ | | | 151808 151809 151810 151811 151812 151813 151814 151815 151816 151817 151818 151819 151820 151821 151822 | 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. ** |
︙ | ︙ | |||
150881 150882 150883 150884 150885 150886 150887 | ** 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); | | | > | > | > > > > > | > | > > | 151831 151832 151833 151834 151835 151836 151837 151838 151839 151840 151841 151842 151843 151844 151845 151846 151847 151848 151849 151850 151851 151852 151853 151854 151855 151856 151857 151858 151859 151860 151861 151862 151863 151864 151865 151866 151867 151868 151869 151870 151871 151872 151873 151874 151875 151876 151877 151878 151879 151880 151881 151882 | ** 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( |
︙ | ︙ | |||
151052 151053 151054 151055 151056 151057 151058 151059 151060 151061 151062 151063 151064 151065 | 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 | > > | 152012 152013 152014 152015 152016 152017 152018 152019 152020 152021 152022 152023 152024 152025 152026 152027 | 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 |
︙ | ︙ | |||
151173 151174 151175 151176 151177 151178 151179 151180 151181 151182 151183 151184 151185 151186 | 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; } | > | 152135 152136 152137 152138 152139 152140 152141 152142 152143 152144 152145 152146 152147 152148 152149 | 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; } |
︙ | ︙ | |||
151883 151884 151885 151886 151887 151888 151889 | #endif { rc = whereLoopAddBtree(&sSubBuild, mPrereq); } if( rc==SQLITE_OK ){ rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable); } | | > > | 152846 152847 152848 152849 152850 152851 152852 152853 152854 152855 152856 152857 152858 152859 152860 152861 152862 | #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; |
︙ | ︙ | |||
152112 152113 152114 152115 152116 152117 152118 | ** 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; | | | 153077 153078 153079 153080 153081 153082 153083 153084 153085 153086 153087 153088 153089 153090 153091 | ** 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 |
︙ | ︙ | |||
152152 152153 152154 152155 152156 152157 152158 152159 152160 152161 152162 152163 152164 152165 | 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. */ | > > > > | 153117 153118 153119 153120 153121 153122 153123 153124 153125 153126 153127 153128 153129 153130 153131 153132 153133 153134 | 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. */ |
︙ | ︙ | |||
152219 152220 152221 152222 152223 152224 152225 | if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; }else{ iColumn = XN_ROWID; revIdx = 0; } /* An unconstrained column that might be NULL means that this | | | | | | | | > > > > | | 153188 153189 153190 153191 153192 153193 153194 153195 153196 153197 153198 153199 153200 153201 153202 153203 153204 153205 153206 153207 153208 153209 153210 153211 153212 153213 153214 153215 153216 153217 153218 153219 153220 153221 153222 153223 153224 153225 153226 153227 153228 | 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; } |
︙ | ︙ | |||
152410 152411 152412 152413 152414 152415 152416 | ** 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 */ | | | 153383 153384 153385 153386 153387 153388 153389 153390 153391 153392 153393 153394 153395 153396 153397 | ** 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 |
︙ | ︙ | |||
153342 153343 153344 153345 153346 153347 153348 | ** ** SELECT DISTINCT v1, v3 FROM t1 ** LEFT JOIN t2 ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) */ notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 | | > | 154315 154316 154317 154318 154319 154320 154321 154322 154323 154324 154325 154326 154327 154328 154329 154330 | ** ** 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); } |
︙ | ︙ | |||
153601 153602 153603 153604 153605 153606 153607 153608 153609 153610 153611 153612 153613 153614 | 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; } /* | > > | 154575 154576 154577 154578 154579 154580 154581 154582 154583 154584 154585 154586 154587 154588 154589 154590 | 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; } /* |
︙ | ︙ | |||
153697 153698 153699 153700 153701 153702 153703 153704 153705 153706 153707 153708 153709 153710 | 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 ){ | > > | 154673 154674 154675 154676 154677 154678 154679 154680 154681 154682 154683 154684 154685 154686 154687 154688 | 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 ){ |
︙ | ︙ | |||
153721 153722 153723 153724 153725 153726 153727 153728 153729 153730 153731 153732 153733 153734 | 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); } | > > > > > | 154699 154700 154701 154702 154703 154704 154705 154706 154707 154708 154709 154710 154711 154712 154713 154714 154715 154716 154717 | 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); } |
︙ | ︙ | |||
153855 153856 153857 153858 153859 153860 153861 | 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); | | | 154838 154839 154840 154841 154842 154843 154844 154845 154846 154847 154848 154849 154850 154851 154852 | 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 |
︙ | ︙ | |||
153900 153901 153902 153903 153904 153905 153906 | }while( (++pOp)<pLastOp ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n"); #endif } } | < < < < < < < < > | 154883 154884 154885 154886 154887 154888 154889 154890 154891 154892 154893 154894 154895 154896 154897 154898 154899 | }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 ******************************************/ |
︙ | ︙ | |||
154707 154708 154709 154710 154711 154712 154713 154714 154715 154716 154717 154718 154719 154720 | } } /* 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; } | > | 155683 155684 155685 155686 155687 155688 155689 155690 155691 155692 155693 155694 155695 155696 155697 | } } /* 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; } |
︙ | ︙ | |||
154816 154817 154818 154819 154820 154821 154822 | 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++){ | > | > > > > | | 155793 155794 155795 155796 155797 155798 155799 155800 155801 155802 155803 155804 155805 155806 155807 155808 155809 155810 155811 155812 155813 155814 | 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; |
︙ | ︙ | |||
154853 154854 154855 154856 154857 154858 154859 154860 154861 154862 154863 154864 154865 154866 154867 154868 154869 | 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; | > > > > > > > > | | 155835 155836 155837 155838 155839 155840 155841 155842 155843 155844 155845 155846 155847 155848 155849 155850 155851 155852 155853 155854 155855 155856 155857 155858 155859 155860 155861 155862 155863 155864 155865 155866 155867 | 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; |
︙ | ︙ | |||
154887 154888 154889 154890 154891 154892 154893 154894 154895 154896 154897 154898 154899 154900 | 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; | > > > > > | 155877 155878 155879 155880 155881 155882 155883 155884 155885 155886 155887 155888 155889 155890 155891 155892 155893 155894 155895 | 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; |
︙ | ︙ | |||
155483 155484 155485 155486 155487 155488 155489 155490 155491 155492 155493 155494 155495 155496 | 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; }; /* | > | 156478 156479 156480 156481 156482 156483 156484 156485 156486 156487 156488 156489 156490 156491 156492 | 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; }; /* |
︙ | ︙ | |||
155599 155600 155601 155602 155603 155604 155605 | 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 ){ | | | | | | 156595 156596 156597 156598 156599 156600 156601 156602 156603 156604 156605 156606 156607 156608 156609 156610 156611 156612 156613 156614 156615 156616 156617 | 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; |
︙ | ︙ | |||
155966 155967 155968 155969 155970 155971 155972 | ** 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 | | > > > > > < < < < < < < < < < < < < < < < < < < < < < < | 156962 156963 156964 156965 156966 156967 156968 156969 156970 156971 156972 156973 156974 156975 156976 156977 156978 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 | ** 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: |
︙ | ︙ | |||
156062 156063 156064 156065 156066 156067 156068 | break; case OP_Le: sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v); break; default: assert( op==OP_Lt ); /* no-op */ break; } | | | > > > > > > > > > > > > > > > > > > > > > > > | 157040 157041 157042 157043 157044 157045 157046 157047 157048 157049 157050 157051 157052 157053 157054 157055 157056 157057 157058 157059 157060 157061 157062 157063 157064 157065 157066 157067 157068 157069 157070 157071 157072 157073 157074 157075 157076 157077 157078 157079 157080 157081 157082 157083 157084 157085 157086 157087 157088 157089 157090 157091 157092 157093 | 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); |
︙ | ︙ | |||
156154 156155 156156 156157 156158 156159 156160 | 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 | | > > | > | | | | > > > > > | 157155 157156 157157 157158 157159 157160 157161 157162 157163 157164 157165 157166 157167 157168 157169 157170 157171 157172 157173 157174 157175 157176 157177 157178 157179 157180 157181 157182 157183 157184 157185 157186 | 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: |
︙ | ︙ | |||
156660 156661 156662 156663 156664 156665 156666 | 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 */ | < | 157669 157670 157671 157672 157673 157674 157675 157676 157677 157678 157679 157680 157681 157682 | 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 */ |
︙ | ︙ | |||
156732 156733 156734 156735 156736 156737 156738 | /* 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; | | | 157740 157741 157742 157743 157744 157745 157746 157747 157748 157749 157750 157751 157752 157753 157754 | /* 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; } |
︙ | ︙ | |||
156788 156789 156790 156791 156792 156793 156794 | 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 */ | | | | | 157796 157797 157798 157799 157800 157801 157802 157803 157804 157805 157806 157807 157808 157809 157810 157811 157812 | 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); |
︙ | ︙ | |||
156908 156909 156910 156911 156912 156913 156914 156915 156916 156917 156918 156919 156920 156921 | /* 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); | > | 157916 157917 157918 157919 157920 157921 157922 157923 157924 157925 157926 157927 157928 157929 157930 | /* 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); |
︙ | ︙ | |||
157381 157382 157383 157384 157385 157386 157387 | #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 | > | | | 158390 158391 158392 158393 158394 158395 158396 158397 158398 158399 158400 158401 158402 158403 158404 158405 158406 | #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. |
︙ | ︙ | |||
157442 157443 157444 157445 157446 157447 157448 | ** YY_MAX_REDUCE Maximum value for reduce actions */ #ifndef INTERFACE # define INTERFACE 1 #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int | | | > | | | > > > | | | | | | < | | < < < | | 158452 158453 158454 158455 158456 158457 158458 158459 158460 158461 158462 158463 158464 158465 158466 158467 158468 158469 158470 158471 158472 158473 158474 158475 158476 158477 158478 158479 158480 158481 158482 158483 158484 158485 158486 158487 158488 158489 158490 158491 158492 158493 158494 158495 158496 158497 158498 158499 158500 158501 158502 158503 158504 158505 158506 158507 | ** 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 |
︙ | ︙ | |||
157558 157559 157560 157561 157562 157563 157564 | ** 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 **********************************************/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 159057 159058 159059 159060 159061 159062 159063 159064 159065 159066 159067 159068 159069 159070 159071 159072 159073 159074 159075 159076 159077 159078 159079 159080 159081 159082 159083 159084 159085 159086 159087 159088 159089 159090 159091 159092 159093 159094 159095 159096 159097 159098 159099 159100 159101 159102 159103 159104 159105 159106 159107 159108 159109 159110 159111 159112 159113 159114 159115 159116 159117 | ** 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, |
︙ | ︙ | |||
158352 158353 158354 158355 158356 158357 158358 158359 158360 158361 158362 158363 158364 158365 | 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: | > | 159363 159364 159365 159366 159367 159368 159369 159370 159371 159372 159373 159374 159375 159376 159377 | 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: |
︙ | ︙ | |||
158623 158624 158625 158626 158627 158628 158629 | /* 174 */ "TRUTH", /* 175 */ "REGISTER", /* 176 */ "VECTOR", /* 177 */ "SELECT_COLUMN", /* 178 */ "IF_NULL_ROW", /* 179 */ "ASTERISK", /* 180 */ "SPAN", | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 159724 159725 159726 159727 159728 159729 159730 159731 159732 159733 159734 159735 159736 159737 159738 159739 159740 159741 159742 159743 159744 159745 159746 159747 159748 159749 159750 159751 159752 159753 159754 159755 159756 159757 159758 159759 159760 159761 159762 159763 159764 159765 159766 159767 159768 159769 159770 159771 159772 159773 159774 159775 159776 159777 159778 159779 159780 159781 159782 159783 159784 | /* 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[] = { |
︙ | ︙ | |||
159288 159289 159290 159291 159292 159293 159294 | ** 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 ***************************************/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | > | | | | | | | | | | | | 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 160347 160348 160349 160350 160351 160352 160353 160354 160355 160356 160357 160358 160359 160360 160361 160362 160363 160364 160365 160366 160367 160368 160369 160370 160371 160372 160373 160374 160375 160376 160377 160378 160379 160380 160381 160382 160383 160384 160385 160386 160387 160388 160389 160390 160391 160392 160393 160394 160395 160396 160397 160398 160399 160400 160401 160402 160403 160404 160405 160406 160407 | ** 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 */ } } |
︙ | ︙ | |||
159671 159672 159673 159674 159675 159676 159677 | 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[] = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 160684 160685 160686 160687 160688 160689 160690 160691 160692 160693 160694 160695 160696 160697 160698 160699 160700 160701 160702 160703 160704 160705 160706 160707 160708 160709 160710 160711 160712 160713 160714 160715 160716 160717 160718 160719 160720 160721 160722 160723 160724 160725 160726 160727 160728 160729 160730 160731 160732 160733 160734 160735 160736 160737 160738 160739 160740 160741 160742 160743 160744 160745 160746 160747 160748 160749 160750 160751 160752 160753 160754 160755 160756 160757 160758 160759 160760 160761 160762 160763 160764 160765 160766 160767 160768 160769 160770 160771 160772 160773 160774 160775 160776 160777 160778 160779 160780 160781 160782 160783 160784 160785 160786 160787 160788 160789 160790 160791 160792 160793 160794 160795 160796 160797 160798 160799 160800 160801 160802 160803 160804 160805 160806 160807 160808 160809 160810 160811 160812 160813 160814 160815 160816 160817 160818 160819 160820 160821 160822 160823 160824 160825 160826 160827 160828 160829 160830 160831 160832 160833 160834 160835 160836 160837 160838 160839 160840 160841 160842 160843 160844 160845 160846 160847 160848 160849 160850 160851 160852 160853 160854 160855 160856 160857 160858 160859 160860 160861 160862 160863 160864 160865 160866 160867 160868 160869 160870 160871 160872 160873 160874 160875 160876 160877 160878 160879 160880 160881 160882 160883 160884 160885 160886 160887 160888 160889 160890 160891 160892 160893 160894 160895 160896 160897 160898 160899 160900 160901 160902 160903 160904 160905 160906 160907 160908 160909 160910 160911 160912 160913 160914 160915 160916 160917 160918 160919 160920 160921 160922 160923 160924 160925 160926 160927 160928 160929 160930 160931 160932 160933 160934 160935 160936 160937 160938 160939 160940 160941 160942 160943 160944 160945 160946 160947 160948 160949 160950 160951 160952 160953 160954 160955 160956 160957 160958 160959 160960 160961 160962 160963 160964 160965 160966 160967 160968 160969 160970 160971 160972 160973 160974 160975 160976 160977 160978 160979 160980 160981 160982 160983 160984 160985 160986 160987 160988 160989 160990 160991 160992 160993 160994 160995 160996 160997 160998 160999 161000 161001 161002 161003 161004 161005 161006 161007 161008 161009 161010 161011 161012 161013 161014 161015 161016 161017 161018 161019 161020 161021 161022 161023 161024 161025 161026 161027 161028 161029 161030 161031 161032 161033 161034 161035 161036 161037 161038 161039 161040 161041 161042 161043 161044 161045 161046 161047 161048 161049 161050 161051 161052 161053 161054 161055 161056 161057 161058 161059 161060 161061 161062 161063 161064 161065 161066 161067 161068 161069 161070 161071 161072 161073 161074 161075 161076 161077 161078 161079 161080 161081 161082 161083 161084 161085 161086 161087 161088 161089 161090 161091 161092 161093 161094 161095 | 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 */ |
︙ | ︙ | |||
160523 160524 160525 160526 160527 160528 160529 | case 1: /* explain ::= EXPLAIN QUERY PLAN */ { pParse->explain = 2; } break; case 2: /* cmdx ::= cmd */ { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ | | | | | 161536 161537 161538 161539 161540 161541 161542 161543 161544 161545 161546 161547 161548 161549 161550 161551 161552 161553 161554 161555 161556 161557 161558 161559 | 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 */ { |
︙ | ︙ | |||
160555 160556 160557 160558 160559 160560 160561 | 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 */ { | | | | < | | | | | | | 161568 161569 161570 161571 161572 161573 161574 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 | 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; |
︙ | ︙ | |||
160624 160625 160626 160627 160628 160629 160630 | 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 ); | | | | | | | | | | | | | | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 162491 162492 162493 162494 162495 162496 162497 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 | 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; |
︙ | ︙ | |||
161544 161545 161546 161547 161548 161549 161550 | {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; | | | | | | | | | | | | | | | | 162559 162560 162561 162562 162563 162564 162565 162566 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 | {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 " |
︙ | ︙ | |||
161613 161614 161615 161616 161617 161618 161619 | { 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 */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | > > > | | | | | | | | | | | | | | | 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 162865 162866 162867 162868 162869 162870 162871 162872 162873 162874 162875 162876 162877 162878 162879 162880 162881 162882 162883 162884 162885 162886 162887 162888 162889 162890 162891 162892 162893 162894 162895 162896 162897 162898 162899 162900 162901 162902 162903 162904 162905 162906 162907 162908 162909 162910 162911 162912 162913 162914 162915 162916 162917 162918 162919 162920 162921 162922 162923 162924 162925 | { 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); |
︙ | ︙ | |||
162359 162360 162361 162362 162363 162364 162365 162366 162367 162368 162369 162370 162371 162372 162373 162374 162375 162376 162377 | #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, | > | | | | | | | | | 163378 163379 163380 163381 163382 163383 163384 163385 163386 163387 163388 163389 163390 163391 163392 163393 163394 163395 163396 163397 163398 163399 163400 163401 163402 163403 163404 163405 163406 163407 163408 163409 163410 163411 163412 | #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, |
︙ | ︙ | |||
163321 163322 163323 163324 163325 163326 163327 163328 163329 163330 163331 163332 163333 163334 | #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; } | > > > > > > > > | 164341 164342 164343 164344 164345 164346 164347 164348 164349 164350 164351 164352 164353 164354 164355 164356 164357 164358 164359 164360 164361 164362 | #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; } |
︙ | ︙ | |||
164340 164341 164342 164343 164344 164345 164346 | if( sqlite3GlobalConfig.isPCacheInit==0 ){ rc = sqlite3PcacheInitialize(); } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } | | | 165368 165369 165370 165371 165372 165373 165374 165375 165376 165377 165378 165379 165380 165381 165382 | 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); |
︙ | ︙ | |||
164755 164756 164757 164758 164759 164760 164761 | iVal = SQLITE_DEFAULT_SORTERREF_SIZE; } sqlite3GlobalConfig.szSorterRef = (u32)iVal; break; } #endif /* SQLITE_ENABLE_SORTER_REFERENCES */ | | | | 165783 165784 165785 165786 165787 165788 165789 165790 165791 165792 165793 165794 165795 165796 165797 165798 165799 165800 165801 165802 | 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); |
︙ | ︙ | |||
165309 165310 165311 165312 165313 165314 165315 | 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 | | | 166337 166338 166339 166340 166341 166342 166343 166344 166345 166346 166347 166348 166349 166350 166351 | 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); } |
︙ | ︙ | |||
165919 165920 165921 165922 165923 165924 165925 165926 165927 165928 165929 165930 165931 165932 | 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; } | > > > > | 166947 166948 166949 166950 166951 166952 166953 166954 166955 166956 166957 166958 166959 166960 166961 166962 166963 166964 | 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; } |
︙ | ︙ | |||
168314 168315 168316 168317 168318 168319 168320 168321 168322 168323 168324 168325 168326 168327 | 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; } /* | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 169346 169347 169348 169349 169350 169351 169352 169353 169354 169355 169356 169357 169358 169359 169360 169361 169362 169363 169364 169365 169366 169367 169368 169369 169370 169371 169372 169373 169374 169375 169376 169377 169378 169379 169380 169381 169382 169383 169384 169385 169386 169387 169388 169389 | 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; } /* |
︙ | ︙ | |||
169756 169757 169758 169759 169760 169761 169762 | #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. */ | | | 170818 170819 170820 170821 170822 170823 170824 170825 170826 170827 170828 170829 170830 170831 170832 | #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 /* |
︙ | ︙ | |||
170312 170313 170314 170315 170316 170317 170318 170319 170320 170321 170322 170323 170324 170325 170326 | /* ** 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){ | > > | 171374 171375 171376 171377 171378 171379 171380 171381 171382 171383 171384 171385 171386 171387 171388 171389 171390 | /* ** 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){ |
︙ | ︙ | |||
171883 171884 171885 171886 171887 171888 171889 | ){ 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 */ | | | | | 172947 172948 172949 172950 172951 172952 172953 172954 172955 172956 172957 172958 172959 172960 172961 172962 172963 172964 172965 172966 172967 172968 172969 172970 172971 172972 172973 172974 172975 172976 172977 172978 | ){ 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 */ |
︙ | ︙ | |||
171953 171954 171955 171956 171957 171958 171959 | ** 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)) ){ | | | | | | 173017 173018 173019 173020 173021 173022 173023 173024 173025 173026 173027 173028 173029 173030 173031 173032 173033 173034 173035 173036 173037 173038 173039 173040 173041 173042 173043 173044 | ** 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; } |
︙ | ︙ | |||
173572 173573 173574 173575 173576 173577 173578 173579 173580 173581 173582 | } /* ** 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 ); | > > > > > | | < > > | | 174636 174637 174638 174639 174640 174641 174642 174643 174644 174645 174646 174647 174648 174649 174650 174651 174652 174653 174654 174655 174656 174657 174658 174659 174660 174661 174662 174663 | } /* ** 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(). */ |
︙ | ︙ | |||
175108 175109 175110 175111 175112 175113 175114 | /* 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; | < < > | 176178 176179 176180 176181 176182 176183 176184 176185 176186 176187 176188 176189 176190 176191 176192 176193 176194 176195 176196 176197 176198 176199 176200 | /* 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); |
︙ | ︙ | |||
176493 176494 176495 176496 176497 176498 176499 176500 176501 176502 176503 176504 176505 176506 | } /* 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]); | > | 177562 177563 177564 177565 177566 177567 177568 177569 177570 177571 177572 177573 177574 177575 177576 | } /* 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]); |
︙ | ︙ | |||
182014 182015 182016 182017 182018 182019 182020 | } }else{ rc = (pLhs->aNode==0) - (pRhs->aNode==0); } if( rc==0 ){ rc = pRhs->iIdx - pLhs->iIdx; } | | | 183084 183085 183086 183087 183088 183089 183090 183091 183092 183093 183094 183095 183096 183097 183098 | } }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: |
︙ | ︙ | |||
182210 182211 182212 182213 182214 182215 182216 | static int fts3PrefixCompress( const char *zPrev, /* Buffer containing previous term */ int nPrev, /* Size of buffer zPrev in bytes */ const char *zNext, /* Buffer containing next term */ int nNext /* Size of buffer zNext in bytes */ ){ int n; | < | > | 183280 183281 183282 183283 183284 183285 183286 183287 183288 183289 183290 183291 183292 183293 183294 183295 | static int fts3PrefixCompress( const char *zPrev, /* Buffer containing previous term */ int nPrev, /* Size of buffer zPrev in bytes */ const char *zNext, /* Buffer containing next term */ int nNext /* Size of buffer zNext in bytes */ ){ int n; for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++); assert_fts3_nc( n<nNext ); return n; } /* ** Add term zTerm to the SegmentNode. It is guaranteed that zTerm is larger ** (according to memcmp) than the previous term. */ |
︙ | ︙ | |||
183210 183211 183212 183213 183214 183215 183216 | }else{ if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB; iDelta = (i64)((u64)iDocid - (u64)iPrev); } nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); | | | 184280 184281 184282 184283 184284 184285 184286 184287 184288 184289 184290 184291 184292 184293 184294 | }else{ if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB; iDelta = (i64)((u64)iDocid - (u64)iPrev); } nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist+FTS3_NODE_PADDING); if( rc ) return rc; if( isFirst ){ char *a = &pCsr->aBuffer[nDoclist]; int nWrite; nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a); |
︙ | ︙ | |||
186024 186025 186026 186027 186028 186029 186030 186031 186032 186033 186034 186035 186036 186037 | /* #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 */ | > > > > | 187094 187095 187096 187097 187098 187099 187100 187101 187102 187103 187104 187105 187106 187107 187108 187109 187110 187111 | /* #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 */ |
︙ | ︙ | |||
186074 186075 186076 186077 186078 186079 186080 | 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 */ | | | | 187148 187149 187150 187151 187152 187153 187154 187155 187156 187157 187158 187159 187160 187161 187162 187163 187164 | 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 */ |
︙ | ︙ | |||
186241 186242 186243 186244 186245 186246 186247 | ** 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. */ | | | 187315 187316 187317 187318 187319 187320 187321 187322 187323 187324 187325 187326 187327 187328 187329 | ** 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). |
︙ | ︙ | |||
186350 186351 186352 186353 186354 186355 186356 | } /* ** 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. */ | | | | 187424 187425 187426 187427 187428 187429 187430 187431 187432 187433 187434 187435 187436 187437 187438 187439 187440 187441 | } /* ** 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; } |
︙ | ︙ | |||
186436 186437 186438 186439 186440 186441 186442 | 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; | | | 187510 187511 187512 187513 187514 187515 187516 187517 187518 187519 187520 187521 187522 187523 187524 | 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 ); |
︙ | ︙ | |||
186482 186483 186484 186485 186486 186487 186488 | 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 ){ | | | 187556 187557 187558 187559 187560 187561 187562 187563 187564 187565 187566 187567 187568 187569 187570 | 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; |
︙ | ︙ | |||
187546 187547 187548 187549 187550 187551 187552 | typedef struct TermOffset TermOffset; typedef struct TermOffsetCtx TermOffsetCtx; struct TermOffset { char *pList; /* Position-list */ | | | | | 188620 188621 188622 188623 188624 188625 188626 188627 188628 188629 188630 188631 188632 188633 188634 188635 188636 188637 188638 188639 188640 188641 188642 188643 188644 188645 188646 188647 188648 188649 188650 188651 188652 188653 188654 | 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); |
︙ | ︙ | |||
188843 188844 188845 188846 188847 188848 188849 | /* 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; | | | 189917 189918 189919 189920 189921 189922 189923 189924 189925 189926 189927 189928 189929 189930 189931 | /* 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++] = '\\'; |
︙ | ︙ | |||
190442 190443 190444 190445 190446 190447 190448 | 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, ','); | < > | 191516 191517 191518 191519 191520 191521 191522 191523 191524 191525 191526 191527 191528 191529 191530 191531 | 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 ){ |
︙ | ︙ | |||
190503 190504 190505 190506 190507 190508 190509 | 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; | | < < < < > | | > > > > | 191577 191578 191579 191580 191581 191582 191583 191584 191585 191586 191587 191588 191589 191590 191591 191592 191593 191594 191595 191596 191597 191598 191599 191600 191601 191602 191603 191604 191605 191606 191607 | 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 /* |
︙ | ︙ | |||
190546 190547 190548 190549 190550 190551 190552 | 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, ','); | < > | 191621 191622 191623 191624 191625 191626 191627 191628 191629 191630 191631 191632 191633 191634 191635 191636 | 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]); } } |
︙ | ︙ | |||
195068 195069 195070 195071 195072 195073 195074 195075 195076 195077 195078 | ** 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]); | > > | > > > | 196143 196144 196145 196146 196147 196148 196149 196150 196151 196152 196153 196154 196155 196156 196157 196158 196159 196160 196161 196162 196163 196164 196165 196166 | ** 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(). */ |
︙ | ︙ | |||
195858 195859 195860 195861 195862 195863 195864 195865 195866 195867 195868 195869 195870 195871 | 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; | > > > > | 196938 196939 196940 196941 196942 196943 196944 196945 196946 196947 196948 196949 196950 196951 196952 196953 196954 196955 | 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; |
︙ | ︙ | |||
196231 196232 196233 196234 196235 196236 196237 | }else{ sqlite3_free(p); aCoord[0].f = mnX; aCoord[1].f = mxX; aCoord[2].f = mnY; aCoord[3].f = mxY; } | | | 197315 197316 197317 197318 197319 197320 197321 197322 197323 197324 197325 197326 197327 197328 197329 | }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. |
︙ | ︙ | |||
200591 200592 200593 200594 200595 200596 200597 | 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); | > > | | 201675 201676 201677 201678 201679 201680 201681 201682 201683 201684 201685 201686 201687 201688 201689 201690 201691 | 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 = ", "; } |
︙ | ︙ | |||
203963 203964 203965 203966 203967 203968 203969 | ** 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 ){ | | < < < < | < | | | < < < | < < < < < < | 205049 205050 205051 205052 205053 205054 205055 205056 205057 205058 205059 205060 205061 205062 205063 205064 205065 205066 205067 205068 205069 205070 | ** 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; |
︙ | ︙ | |||
205597 205598 205599 205600 205601 205602 205603 205604 205605 205606 205607 205608 205609 205610 205611 205612 205613 205614 205615 205616 205617 | /* ** 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 */ }; /* | > > | 206669 206670 206671 206672 206673 206674 206675 206676 206677 206678 206679 206680 206681 206682 206683 206684 206685 206686 206687 206688 206689 206690 206691 | /* ** 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 */ }; /* |
︙ | ︙ | |||
205846 205847 205848 205849 205850 205851 205852 | */ /* ** For each row modified during a session, there exists a single instance of ** this structure stored in a SessionTable.aChange[] hash table. */ struct SessionChange { | | | > | 206920 206921 206922 206923 206924 206925 206926 206927 206928 206929 206930 206931 206932 206933 206934 206935 206936 | */ /* ** 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 |
︙ | ︙ | |||
206676 206677 206678 206679 206680 206681 206682 206683 206684 206685 206686 206687 206688 206689 | 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 | > > > > > > | 207751 207752 207753 207754 207755 207756 207757 207758 207759 207760 207761 207762 207763 207764 207765 207766 207767 207768 207769 207770 | 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 |
︙ | ︙ | |||
206721 206722 206723 206724 206725 206726 206727 206728 206729 206730 206731 206732 206733 206734 | 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 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 207852 207853 207854 207855 207856 207857 207858 207859 207860 207861 207862 207863 207864 207865 207866 207867 207868 207869 207870 207871 207872 207873 207874 207875 207876 207877 207878 207879 207880 207881 207882 207883 207884 207885 207886 207887 207888 207889 207890 207891 207892 207893 207894 207895 207896 207897 207898 207899 207900 207901 207902 207903 207904 207905 207906 207907 207908 207909 207910 207911 207912 | 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 |
︙ | ︙ | |||
206794 206795 206796 206797 206798 206799 206800 | 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). */ | < | 207972 207973 207974 207975 207976 207977 207978 207979 207980 207981 207982 207983 207984 207985 | 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 */ |
︙ | ︙ | |||
206820 206821 206822 206823 206824 206825 206826 | /* 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 */ | | | | | | | | | | | | > > > > > > | 207997 207998 207999 208000 208001 208002 208003 208004 208005 208006 208007 208008 208009 208010 208011 208012 208013 208014 208015 208016 208017 208018 208019 208020 208021 208022 208023 208024 208025 208026 208027 208028 208029 208030 208031 208032 208033 208034 208035 208036 208037 208038 208039 208040 208041 208042 208043 208044 208045 208046 208047 208048 208049 208050 208051 208052 208053 208054 208055 208056 208057 208058 208059 | /* 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 ){ |
︙ | ︙ | |||
207418 207419 207420 207421 207422 207423 207424 | /* ** 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. */ | | > > | > > | > > > > > > > > > > > > | 208601 208602 208603 208604 208605 208606 208607 208608 208609 208610 208611 208612 208613 208614 208615 208616 208617 208618 208619 208620 208621 208622 208623 208624 208625 208626 208627 208628 208629 208630 208631 208632 208633 208634 208635 208636 208637 | /* ** 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; |
︙ | ︙ | |||
208075 208076 208077 208078 208079 208080 208081 | ** 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 */ ){ | | > > > > | 209274 209275 209276 209277 209278 209279 209280 209281 209282 209283 209284 209285 209286 209287 209288 209289 209290 209291 209292 | ** 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, |
︙ | ︙ | |||
208166 208167 208168 208169 208170 208171 208172 208173 208174 208175 208176 208177 208178 208179 | /* ** 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), | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 209369 209370 209371 209372 209373 209374 209375 209376 209377 209378 209379 209380 209381 209382 209383 209384 209385 209386 209387 209388 209389 209390 209391 209392 209393 209394 209395 209396 209397 209398 209399 209400 209401 209402 209403 209404 209405 209406 209407 209408 209409 209410 209411 209412 209413 209414 209415 | /* ** 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), |
︙ | ︙ | |||
214987 214988 214989 214990 214991 214992 214993 214994 214995 214996 214997 214998 214999 215000 215001 215002 215003 215004 215005 215006 | /* EOF */ *piOff = -1; return 1; }else{ i64 iOff = *piOff; int iVal; fts5FastGetVarint32(a, i, iVal); if( iVal<=1 ){ if( iVal==0 ){ *pi = i; return 0; } fts5FastGetVarint32(a, i, iVal); iOff = ((i64)iVal) << 32; fts5FastGetVarint32(a, i, iVal); if( iVal<2 ){ /* This is a corrupt record. So stop parsing it here. */ *piOff = -1; return 1; } | > < | > > > > | 216223 216224 216225 216226 216227 216228 216229 216230 216231 216232 216233 216234 216235 216236 216237 216238 216239 216240 216241 216242 216243 216244 216245 216246 216247 216248 216249 216250 216251 216252 216253 216254 216255 216256 | /* EOF */ *piOff = -1; return 1; }else{ i64 iOff = *piOff; int iVal; fts5FastGetVarint32(a, i, iVal); assert( iVal>=0 ); if( iVal<=1 ){ if( iVal==0 ){ *pi = i; return 0; } fts5FastGetVarint32(a, i, iVal); iOff = ((i64)iVal) << 32; fts5FastGetVarint32(a, i, iVal); if( iVal<2 ){ /* This is a corrupt record. So stop parsing it here. */ *piOff = -1; return 1; } *piOff = iOff + ((iVal-2) & 0x7FFFFFFF); }else{ *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF); } *pi = i; assert( *piOff>=iOff ); return 0; } } /* ** Advance the iterator object passed as the only argument. Return true |
︙ | ︙ | |||
215041 215042 215043 215044 215045 215046 215047 | ** to iPos before returning. */ static void sqlite3Fts5PoslistSafeAppend( Fts5Buffer *pBuf, i64 *piPrev, i64 iPos ){ | > | | | | | | | | > | 216281 216282 216283 216284 216285 216286 216287 216288 216289 216290 216291 216292 216293 216294 216295 216296 216297 216298 216299 216300 216301 216302 216303 216304 | ** to iPos before returning. */ static void sqlite3Fts5PoslistSafeAppend( Fts5Buffer *pBuf, i64 *piPrev, i64 iPos ){ if( iPos>=*piPrev ){ static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; if( (iPos & colmask) != (*piPrev & colmask) ){ pBuf->p[pBuf->n++] = 1; pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); *piPrev = (iPos & colmask); } pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); *piPrev = iPos; } } static int sqlite3Fts5PoslistWriterAppend( Fts5Buffer *pBuf, Fts5PoslistWriter *pWriter, i64 iPos ){ |
︙ | ︙ | |||
215750 215751 215752 215753 215754 215755 215756 | 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); | | | 216992 216993 216994 216995 216996 216997 216998 216999 217000 217001 217002 217003 217004 217005 217006 | 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 |
︙ | ︙ | |||
218586 218587 218588 218589 218590 218591 218592 218593 218594 218595 218596 218597 218598 218599 | 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){ | > | 219828 219829 219830 219831 219832 219833 219834 219835 219836 219837 219838 219839 219840 219841 219842 | 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){ |
︙ | ︙ | |||
218952 218953 218954 218955 218956 218957 218958 218959 218960 218961 218962 218963 218964 218965 218966 218967 218968 218969 218970 218971 218972 218973 218974 218975 218976 218977 218978 218979 218980 218981 218982 218983 218984 218985 218986 218987 218988 | 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; | > > > > > > | 220195 220196 220197 220198 220199 220200 220201 220202 220203 220204 220205 220206 220207 220208 220209 220210 220211 220212 220213 220214 220215 220216 220217 220218 220219 220220 220221 220222 220223 220224 220225 220226 220227 220228 220229 220230 220231 220232 220233 220234 220235 220236 220237 | 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; |
︙ | ︙ | |||
220221 220222 220223 220224 220225 220226 220227 | */ 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) */ | | | 221470 221471 221472 221473 221474 221475 221476 221477 221478 221479 221480 221481 221482 221483 221484 | */ 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; |
︙ | ︙ | |||
221401 221402 221403 221404 221405 221406 221407 | } pIter->iLeafOffset = iOff; } } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ | | | 222650 222651 222652 222653 222654 222655 222656 222657 222658 222659 222660 222661 222662 222663 222664 | } 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; |
︙ | ︙ | |||
221434 221435 221436 221437 221438 221439 221440 | ** ** 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 */ | | | 222683 222684 222685 222686 222687 222688 222689 222690 222691 222692 222693 222694 222695 222696 222697 | ** ** 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; } |
︙ | ︙ | |||
221862 221863 221864 221865 221866 221867 221868 | 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; | < | 223111 223112 223113 223114 223115 223116 223117 223118 223119 223120 223121 223122 223123 223124 | 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 ); } } |
︙ | ︙ | |||
222974 222975 222976 222977 222978 222979 222980 | if( pColset->nCol==1 ){ pIter->base.pData = aCopy; pIter->base.nData = p-aCopy; return; } fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy); } | | | 224222 224223 224224 224225 224226 224227 224228 224229 224230 224231 224232 224233 224234 224235 224236 | if( pColset->nCol==1 ){ pIter->base.pData = aCopy; pIter->base.nData = p-aCopy; return; } fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy); } if( p>=pEnd ){ pIter->base.pData = pIter->poslist.p; pIter->base.nData = pIter->poslist.n; return; } aCopy = p++; iCurrent = *p++; if( iCurrent & 0x80 ){ |
︙ | ︙ | |||
224331 224332 224333 224334 224335 224336 224337 | 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; | | | | 225579 225580 225581 225582 225583 225584 225585 225586 225587 225588 225589 225590 225591 225592 225593 225594 225595 225596 225597 225598 225599 225600 | 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); |
︙ | ︙ | |||
224770 224771 224772 224773 224774 224775 224776 | static void fts5MergePrefixLists( Fts5Index *p, /* FTS5 backend object */ Fts5Buffer *p1, /* First list to merge */ int nBuf, /* Number of buffers in array aBuf[] */ Fts5Buffer *aBuf /* Other lists to merge in */ ){ #define fts5PrefixMergerNextPosition(p) \ | | | 226018 226019 226020 226021 226022 226023 226024 226025 226026 226027 226028 226029 226030 226031 226032 | static void fts5MergePrefixLists( Fts5Index *p, /* FTS5 backend object */ Fts5Buffer *p1, /* First list to merge */ int nBuf, /* Number of buffers in array aBuf[] */ Fts5Buffer *aBuf /* Other lists to merge in */ ){ #define fts5PrefixMergerNextPosition(p) \ sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos) #define FTS5_MERGE_NLIST 16 PrefixMerger aMerger[FTS5_MERGE_NLIST]; PrefixMerger *pHead = 0; int i; int nOut = 0; Fts5Buffer out = {0, 0, 0}; Fts5Buffer tmp = {0, 0, 0}; |
︙ | ︙ | |||
224869 224870 224871 224872 224873 224874 224875 | if( pHead->iPos!=iPrev ){ sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos); } nTail = pHead->iter.nPoslist - pHead->iOff; /* WRITEPOSLISTSIZE */ | > | | 226117 226118 226119 226120 226121 226122 226123 226124 226125 226126 226127 226128 226129 226130 226131 226132 | 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 ){ |
︙ | ︙ | |||
226016 226017 226018 226019 226020 226021 226022 226023 226024 226025 226026 226027 226028 226029 | /************************************************************************* ************************************************************************** ** 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 */ | > | 227265 227266 227267 227268 227269 227270 227271 227272 227273 227274 227275 227276 227277 227278 227279 | /************************************************************************* ************************************************************************** ** 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 */ |
︙ | ︙ | |||
226038 226039 226040 226041 226042 226043 226044 226045 226046 226047 226048 226049 226050 226051 226052 226053 226054 226055 226056 226057 226058 226059 226060 226061 226062 226063 226064 226065 226066 226067 226068 226069 226070 | 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 */ | > > > > | 227288 227289 227290 227291 227292 227293 227294 227295 227296 227297 227298 227299 227300 227301 227302 227303 227304 227305 227306 227307 227308 227309 227310 227311 227312 227313 227314 227315 227316 227317 227318 227319 227320 227321 227322 227323 227324 | 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 */ |
︙ | ︙ | |||
226078 226079 226080 226081 226082 226083 226084 226085 226086 226087 226088 226089 226090 226091 226092 | 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. */ | > > | 227332 227333 227334 227335 227336 227337 227338 227339 227340 227341 227342 227343 227344 227345 227346 227347 227348 | 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. */ |
︙ | ︙ | |||
226103 226104 226105 226106 226107 226108 226109 226110 226111 226112 226113 226114 226115 226116 226117 | *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. */ | > > | 227359 227360 227361 227362 227363 227364 227365 227366 227367 227368 227369 227370 227371 227372 227373 227374 227375 | *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. */ |
︙ | ︙ | |||
226126 226127 226128 226129 226130 226131 226132 226133 226134 226135 226136 226137 226138 226139 226140 226141 226142 226143 226144 226145 226146 226147 226148 226149 226150 226151 226152 226153 226154 226155 226156 226157 | 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. | > > > > | 227384 227385 227386 227387 227388 227389 227390 227391 227392 227393 227394 227395 227396 227397 227398 227399 227400 227401 227402 227403 227404 227405 227406 227407 227408 227409 227410 227411 227412 227413 227414 227415 227416 227417 227418 227419 | 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. |
︙ | ︙ | |||
226176 226177 226178 226179 226180 226181 226182 226183 226184 226185 226186 226187 226188 226189 226190 | 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. | > > | 227438 227439 227440 227441 227442 227443 227444 227445 227446 227447 227448 227449 227450 227451 227452 227453 227454 | 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. |
︙ | ︙ | |||
226217 226218 226219 226220 226221 226222 226223 226224 226225 226226 226227 226228 226229 226230 226231 | 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 */ | > > | 227481 227482 227483 227484 227485 227486 227487 227488 227489 227490 227491 227492 227493 227494 227495 227496 227497 | 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 */ |
︙ | ︙ | |||
226426 226427 226428 226429 226430 226431 226432 226433 226434 226435 226436 226437 226438 226439 226440 | 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 */ | > > | 227692 227693 227694 227695 227696 227697 227698 227699 227700 227701 227702 227703 227704 227705 227706 227707 227708 | 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 */ |
︙ | ︙ | |||
226460 226461 226462 226463 226464 226465 226466 226467 226468 226469 226470 226471 226472 226473 226474 226475 226476 226477 226478 226479 226480 226481 226482 226483 226484 226485 226486 226487 226488 226489 226490 226491 226492 226493 226494 226495 226496 226497 226498 226499 226500 | }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); | > > > > > > | 227728 227729 227730 227731 227732 227733 227734 227735 227736 227737 227738 227739 227740 227741 227742 227743 227744 227745 227746 227747 227748 227749 227750 227751 227752 227753 227754 227755 227756 227757 227758 227759 227760 227761 227762 227763 227764 227765 227766 227767 227768 227769 227770 227771 227772 227773 227774 | }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); |
︙ | ︙ | |||
226522 226523 226524 226525 226526 226527 226528 226529 226530 226531 226532 226533 226534 226535 226536 | /* ** 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; | > > | 227796 227797 227798 227799 227800 227801 227802 227803 227804 227805 227806 227807 227808 227809 227810 227811 227812 | /* ** 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; |
︙ | ︙ | |||
228447 228448 228449 228450 228451 228452 228453 | iBest = i; } } if( iBest<0 ) break; nInst++; if( nInst>=pCsr->nInstAlloc ){ | | | > > | 229723 229724 229725 229726 229727 229728 229729 229730 229731 229732 229733 229734 229735 229736 229737 229738 229739 229740 229741 229742 229743 229744 229745 | 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; |
︙ | ︙ | |||
229288 229289 229290 229291 229292 229293 229294 | 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); | | | 230566 230567 230568 230569 230570 230571 230572 230573 230574 230575 230576 230577 230578 230579 230580 | 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-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70", -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){ |
︙ | ︙ | |||
234214 234215 234216 234217 234218 234219 234220 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ | | | | 235492 235493 235494 235495 235496 235497 235498 235499 235500 235501 235502 235503 235504 235505 | #endif return rc; } #endif /* SQLITE_CORE */ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ #if __LINE__!=235499 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2021-06-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9alt2" #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-14 20:41:20 e5a5acd6006133c5da4a7dd79726dbaa41c0d60ebeda890f848a6aafe5f9ef70" /* ** 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 72 | /* ** 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; double rDigest; @ <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" | > | > > > > > > > > > > > | 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 | @ </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> rDigest = db_double(-1.0, "SELECT (julianday('now') - value)*24.0" " FROM config WHERE name='email-last-digest'"); if( rDigest>0.0 ){ @ <tr><th>Last Digest:</th><td>Approximately \ if( rDigest>48.0 ){ @ %.1f(rDigest/24.0) days ago</td> }else{ @ %.1f(rDigest) hours ago</td> } } } /* ** WEBPAGE: stat ** ** Show statistics and global information about the repository. */ |
︙ | ︙ |
Changes to src/style.c.
︙ | ︙ | |||
328 329 330 331 332 333 334 | aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az; aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL; aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; nSubmenuCtrl++; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 | aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az; aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL; aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI; nSubmenuCtrl++; } } /* ** Disable or enable the submenu */ void style_submenu_enable(int onOff){ submenuEnable = onOff; } |
︙ | ︙ | |||
965 966 967 968 969 970 971 972 973 974 975 976 977 978 | cgi_tag_query_parameter("udc"); } @ <div class="submenu"> if( nSubmenu>0 ){ qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); for(i=0; i<nSubmenu; i++){ struct Submenu *p = &aSubmenu[i]; if( p->zLink==0 ){ @ <span class="label">%h(p->zLabel)</span> }else{ @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> } } } | > > > > | 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | cgi_tag_query_parameter("udc"); } @ <div class="submenu"> if( nSubmenu>0 ){ qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare); for(i=0; i<nSubmenu; i++){ struct Submenu *p = &aSubmenu[i]; /* switching away from the %h formatting below might be dangerous ** because some places use %s to compose zLabel and zLink; ** e.g. /rptview page */ if( p->zLink==0 ){ @ <span class="label">%h(p->zLabel)</span> }else{ @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a> } } } |
︙ | ︙ |
Changes to src/sync.c.
︙ | ︙ | |||
190 191 192 193 194 195 196 | /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ** Pull all sharable changes from a remote repository into the local ** repository. Sharable changes include public check-ins, edits to | | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ** Pull all sharable changes from a remote repository into the local ** repository. Sharable changes include public check-ins, edits to ** wiki pages, tickets, tech-notes, and forum posts. Add ** the --private option to pull private branches. Use the ** "configuration pull" command to pull website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** |
︙ | ︙ | |||
241 242 243 244 245 246 247 | /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ** Push all sharable changes from the local repository to a remote ** repository. Sharable changes include public check-ins, edits to | | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ** Push all sharable changes from the local repository to a remote ** repository. Sharable changes include public check-ins, edits to ** wiki pages, tickets, tech-notes, and forum posts. Use ** --private to also push private branches. Use the "configuration ** push" command to push website configuration details. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** |
︙ | ︙ | |||
288 289 290 291 292 293 294 | /* ** COMMAND: sync ** ** Usage: %fossil sync ?URL? ?options? ** ** Synchronize all sharable changes between the local repository and a ** remote repository. Sharable changes include public check-ins and | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | /* ** COMMAND: sync ** ** Usage: %fossil sync ?URL? ?options? ** ** Synchronize all sharable changes between the local repository and a ** remote repository. Sharable changes include public check-ins and ** edits to wiki pages, tickets, forum posts, and technical notes. ** ** If URL is not specified, then the URL from the most recent clone, push, ** pull, remote, or sync command is used. See "fossil help clone" for ** details on the URL formats. ** ** Options: ** |
︙ | ︙ |
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/th_main.c.
︙ | ︙ | |||
2974 2975 2976 2977 2978 2979 2980 | /* ** COMMAND: test-th-eval ** ** Usage: %fossil test-th-eval SCRIPT ** ** Evaluate SCRIPT as if it were a header or footer or ticket rendering | | > > > | 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 | /* ** COMMAND: test-th-eval ** ** Usage: %fossil test-th-eval SCRIPT ** ** Evaluate SCRIPT as if it were a header or footer or ticket rendering ** script and show the results on standard output. SCRIPT may be either ** a filename or a string of th1 script code. ** ** Options: ** ** --cgi Include a CGI response header in the output ** --http Include an HTTP response header in the output ** --open-config Open the configuration database ** --set-anon-caps Set anonymous login capabilities ** --set-user-caps Set user login capabilities ** --th-trace Trace TH1 execution (for debugging purposes) */ void test_th_eval(void){ int rc; const char *zRc; const char *zCode = 0; int forceCgi, fullHttpReply; Blob code = empty_blob; Th_InitTraceLog(); forceCgi = find_option("cgi", 0, 0)!=0; fullHttpReply = find_option("http", 0, 0)!=0; if( fullHttpReply ) forceCgi = 1; if( forceCgi ) Th_ForceCgi(fullHttpReply); if( find_option("open-config", 0, 0)!=0 ){ Th_OpenConfig(1); |
︙ | ︙ | |||
3010 3011 3012 3013 3014 3015 3016 3017 3018 | const char *zCap = fossil_getenv("TH1_TEST_USER_CAPS"); login_set_capabilities(zCap ? zCap : "sx", 0); g.useLocalauth = 1; } verify_all_options(); if( g.argc!=3 ){ usage("script"); } Th_FossilInit(TH_INIT_DEFAULT); | > > > > > > | > | 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 | const char *zCap = fossil_getenv("TH1_TEST_USER_CAPS"); login_set_capabilities(zCap ? zCap : "sx", 0); g.useLocalauth = 1; } verify_all_options(); if( g.argc!=3 ){ usage("script"); } if(file_isfile(g.argv[2], ExtFILE)){ blob_read_from_file(&code, g.argv[2], ExtFILE); zCode = blob_str(&code); }else{ zCode = g.argv[2]; } Th_FossilInit(TH_INIT_DEFAULT); rc = Th_Eval(g.interp, 0, zCode, -1); zRc = Th_ReturnCodeName(rc, 1); fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0)); Th_PrintTraceLog(); blob_reset(&code); if( forceCgi ) cgi_reply(); } /* ** COMMAND: test-th-source ** ** Usage: %fossil test-th-source FILE |
︙ | ︙ |
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/tkt.c.
︙ | ︙ | |||
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 | /* ** An authorizer function for the SQL used to initialize the ** schema for the ticketing system. Only allow ** ** CREATE TABLE ** CREATE INDEX ** CREATE VIEW ** ** And for objects in "main" or "repository" whose names ** begin with "ticket" or "fx_". Also allow ** ** INSERT ** UPDATE ** DELETE ** ** But only for tables in "main" or "repository" whose names ** begin with "ticket", "sqlite_", or "fx_". ** ** Of particular importance for security is that this routine ** disallows data changes on the "config" table, as that could ** allow a malicious server to modify settings in such a way as ** to cause a remote code execution. */ static int ticket_schema_auth( void *pNErr, int eCode, const char *z0, const char *z1, const char *z2, const char *z3 ){ switch( eCode ){ case SQLITE_CREATE_VIEW: case SQLITE_CREATE_TABLE: { if( sqlite3_stricmp(z2,"main")!=0 && sqlite3_stricmp(z2,"repository")!=0 ){ goto ticket_schema_error; } if( sqlite3_strnicmp(z0,"ticket",6)!=0 && sqlite3_strnicmp(z0,"fx_",3)!=0 ){ goto ticket_schema_error; } break; } case SQLITE_CREATE_INDEX: { if( sqlite3_stricmp(z2,"main")!=0 && sqlite3_stricmp(z2,"repository")!=0 ){ goto ticket_schema_error; } if( sqlite3_strnicmp(z1,"ticket",6)!=0 | > > > > > > > | 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 | /* ** An authorizer function for the SQL used to initialize the ** schema for the ticketing system. Only allow ** ** CREATE TABLE ** CREATE INDEX ** CREATE VIEW ** DROP INDEX ** DROP VIEW ** ** And for objects in "main" or "repository" whose names ** begin with "ticket" or "fx_". Also allow ** ** INSERT ** UPDATE ** DELETE ** ** But only for tables in "main" or "repository" whose names ** begin with "ticket", "sqlite_", or "fx_". ** ** Of particular importance for security is that this routine ** disallows data changes on the "config" table, as that could ** allow a malicious server to modify settings in such a way as ** to cause a remote code execution. ** ** Use the "fossil test-db-prepare --auth-ticket SQL" command to perform ** manual testing of this authorizer. */ static int ticket_schema_auth( void *pNErr, int eCode, const char *z0, const char *z1, const char *z2, const char *z3 ){ switch( eCode ){ case SQLITE_DROP_VIEW: case SQLITE_CREATE_VIEW: case SQLITE_CREATE_TABLE: { if( sqlite3_stricmp(z2,"main")!=0 && sqlite3_stricmp(z2,"repository")!=0 ){ goto ticket_schema_error; } if( sqlite3_strnicmp(z0,"ticket",6)!=0 && sqlite3_strnicmp(z0,"fx_",3)!=0 ){ goto ticket_schema_error; } break; } case SQLITE_DROP_INDEX: case SQLITE_CREATE_INDEX: { if( sqlite3_stricmp(z2,"main")!=0 && sqlite3_stricmp(z2,"repository")!=0 ){ goto ticket_schema_error; } if( sqlite3_strnicmp(z1,"ticket",6)!=0 |
︙ | ︙ | |||
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | return SQLITE_OK; ticket_schema_error: if( pNErr ) *(int*)pNErr = 1; return SQLITE_DENY; } /* ** Recreate the TICKET and TICKETCHNG tables. */ void ticket_create_table(int separateConnection){ char *zSql; db_multi_exec( "DROP TABLE IF EXISTS ticket;" "DROP TABLE IF EXISTS ticketchng;" ); zSql = ticket_table_schema(); | > > > > > > > > > > > > > > | | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | return SQLITE_OK; ticket_schema_error: if( pNErr ) *(int*)pNErr = 1; return SQLITE_DENY; } /* ** Activate the ticket schema authorizer. Must be followed by ** an eventual call to ticket_unrestrict_sql(). */ void ticket_restrict_sql(int * pNErr){ db_set_authorizer(ticket_schema_auth,(void*)pNErr,"Ticket-Schema"); } /* ** Deactivate the ticket schema authorizer. */ void ticket_unrestrict_sql(void){ db_clear_authorizer(); } /* ** Recreate the TICKET and TICKETCHNG tables. */ void ticket_create_table(int separateConnection){ char *zSql; db_multi_exec( "DROP TABLE IF EXISTS ticket;" "DROP TABLE IF EXISTS ticketchng;" ); zSql = ticket_table_schema(); ticket_restrict_sql(0); if( separateConnection ){ if( db_transaction_nesting_depth() ) db_end_transaction(0); db_init_database(g.zRepositoryName, zSql, 0); }else{ db_multi_exec("%s", zSql/*safe-for-%s*/); } ticket_unrestrict_sql(); fossil_free(zSql); } /* ** Repopulate the TICKET and TICKETCHNG tables from scratch using all ** available ticket artifacts. */ |
︙ | ︙ |
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/wiki.c.
︙ | ︙ | |||
593 594 595 596 597 598 599 | ){ style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName); }else if( rid && g.perm.ApndWiki ){ style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName); } if( g.perm.Hyperlink ){ style_submenu_element("History", "%R/whistory?name=%T", zPageName); | < | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | ){ style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName); }else if( rid && g.perm.ApndWiki ){ style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName); } if( g.perm.Hyperlink ){ style_submenu_element("History", "%R/whistory?name=%T", zPageName); } } if( !isPopup ){ if( zHashsum ){ char *zDate = db_text(0,"SELECT strftime('%%Y-%%m-%%d %%H:%%M'," "'%.17g',toLocal())",pWiki->rDate); Th_Store("wiki_timestamp",zDate); |
︙ | ︙ | |||
646 647 648 649 650 651 652 653 654 655 656 657 658 659 | 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. */ | > > > | 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 | 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. */ |
︙ | ︙ | |||
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | 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(","); | > > | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | 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(","); |
︙ | ︙ | |||
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>"); | | | 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 | "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, |
︙ | ︙ | |||
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>: | | | 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | 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(); |
︙ | ︙ | |||
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | @ count(*) AS wcnt @ FROM @ tag, @ tagxref @ WHERE @ tag.tagname GLOB 'wiki-*' @ AND tagxref.tagid=tag.tagid @ GROUP BY 1 @ ORDER BY 2; ; /* ** WEBPAGE: wcontent ** | > | 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 | @ 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 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 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/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/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 33 34 35 36 37 38 39 40 41 42 43 44 45 | <title>Change Log</title> <a name='v2_16'></a> <h2>Changes for Version 2.16 (pending)</h2> * <b>Security:</b> Fix the client-side TLS so that it verifies that the server hostname matches its certificate. <b>Upgrading to the patch is recommended.</b> * 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. * [./caps/login-groups.md|Login-Groups] are now show on the repository list of the "[/help?cmd=all|fossil all ui]" command. * Administrators can configure [./alerts|email alerts] to expire a specific number of days (ex: 365) after the last user contact with the Fossil server This can prevents alert emails being sent to abandoned email accounts forever. <a name='v2_15'></a> <h2>Changes for Version 2.15 (2021-03-26) and Patch 2.15.1 on (2021-04-07) and 2.15.2 on (2021-06-15)</h2> * <b>Patch 2.15.2:</b> Fix the client-side TLS so that it verifies that the server hostname matches its certificate. <b>Upgrading to the patch is recommended.</b> * <b>Patch 2.15.1:</b> Fix a data exfiltration bug in the server. <b>Upgrading to the patch is recommended.</b> * 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. |
︙ | ︙ | |||
76 77 78 79 80 81 82 | * 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> | | | > > > > > | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | * 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) and 2.14.2 on (2021-06-15)</h2> * <b>Patch 2.14.2:</b> Fix the client-side TLS so that it verifies that the server hostname matches its certificate. <b>Upgrading to the patch is recommended.</b>< * <b>Patch 2.14.1:</b> Fix a data exfiltration bug in the server. <b>Upgrading to the patch is recommended.</b> * <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/index.wiki.
︙ | ︙ | |||
80 81 82 83 84 85 86 | atomic even if interrupted by a power loss or system crash. Automatic [./selfcheck.wiki | self-checks] verify that all aspects of the repository are consistent prior to each commit. 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license]. <hr> | | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | atomic even if interrupted by a power loss or system crash. Automatic [./selfcheck.wiki | self-checks] verify that all aspects of the repository are consistent prior to each commit. 8. <b>Free and Open-Source</b> - [../COPYRIGHT-BSD2.txt|2-clause BSD license]. <hr> <h3>Latest Release: 2.15.2 ([/timeline?c=version-2.15.2|2021-06-15])</h3> * [/uv/download.html|Download] * [./changes.wiki#v2_15|Change Summary] * [/timeline?p=version-2.15.2&bt=version-2.14&y=ci|Check-ins in version 2.15.2] * [/timeline?df=version-2.15&y=ci|Check-ins derived from the 2.15 release] * [/timeline?t=release|Timeline of all past releases] <hr> <h3>Quick Start</h3> 1. [/uv/download.html|Download] or install using a package manager or |
︙ | ︙ |
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 the [`/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 |
︙ | ︙ | |||
604 605 606 607 608 609 610 | 1) Features the developers themselves want to have and/or work on. 2) Features end users request which catch the interest of one or more developers, provided the developer(s) in question are in a position to expend the effort. 3) Features end users and co-contributors can convince a developer into | | | 617 618 619 620 621 622 623 624 625 626 627 628 629 630 | 1) Features the developers themselves want to have and/or work on. 2) Features end users request which catch the interest of one or more developers, provided the developer(s) in question are in a position to expend the effort. 3) Features end users and co-contributors can convince a developer into coding even when they really don't want to. In all of this, Fossil's project lead understandably has the final say-so in whether any given feature indeed gets merged into the mainline trunk. Development of any given feature, no matter how much effort was involved, does not guarantee its eventual inclusion into the public releases. |
Changes to www/mkindex.tcl.
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 | tech_overview.wiki {SQLite Databases Used By Fossil} th1.md {The TH1 Scripting Language} theory1.wiki {Thoughts On The Design Of The Fossil DVCS} tickets.wiki {The Fossil Ticket System} unvers.wiki {Unversioned Files} webpage-ex.md {Webpage Examples} webui.wiki {The Fossil Web Interface} whyusefossil.wiki {Why You Should Use Fossil} whyusefossil.wiki {Benefits Of Version Control} wikitheory.wiki {Wiki In Fossil} /wiki_rules {Wiki Formatting Rules} } set permindex {} | > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | tech_overview.wiki {SQLite Databases Used By Fossil} th1.md {The TH1 Scripting Language} theory1.wiki {Thoughts On The Design Of The Fossil DVCS} tickets.wiki {The Fossil Ticket System} unvers.wiki {Unversioned Files} webpage-ex.md {Webpage Examples} webui.wiki {The Fossil Web Interface} whyallinone.md {Why Bundle Forum, Wiki, and other Web Software With Your DVCS?} whyusefossil.wiki {Why You Should Use Fossil} whyusefossil.wiki {Benefits Of Version Control} wikitheory.wiki {Wiki In Fossil} /wiki_rules {Wiki Formatting Rules} } set permindex {} |
︙ | ︙ |
Changes to www/permutedindex.html.
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> <li><a href="unvers.wiki">Unversioned Files</a></li> <li><a href="fiveminutes.wiki">Up and Running in 5 Minutes as a Single User</a></li> <li><a href="javascript.md">Use of JavaScript in Fossil</a></li> <li><a href="caps/ref.html">User Capability Reference</a></li> <li><a href="ssl.wiki">Using SSL with Fossil</a></li> <li><a href="webpage-ex.md">Webpage Examples</a></li> <li><a href="whyusefossil.wiki">Why You Should Use Fossil</a></li> <li><a href="../../../wiki_rules">Wiki Formatting Rules</a></li> <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> </ul></div> | > | 123 124 125 126 127 128 129 130 131 132 133 134 | <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> <li><a href="unvers.wiki">Unversioned Files</a></li> <li><a href="fiveminutes.wiki">Up and Running in 5 Minutes as a Single User</a></li> <li><a href="javascript.md">Use of JavaScript in Fossil</a></li> <li><a href="caps/ref.html">User Capability Reference</a></li> <li><a href="ssl.wiki">Using SSL with Fossil</a></li> <li><a href="webpage-ex.md">Webpage Examples</a></li> <li><a href="whyallinone.md">Why Bundle Forum, Wiki, and other Web Software With Your DVCS?</a></li> <li><a href="whyusefossil.wiki">Why You Should Use Fossil</a></li> <li><a href="../../../wiki_rules">Wiki Formatting Rules</a></li> <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> </ul></div> |
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 |
︙ | ︙ | |||
501 502 503 504 505 506 507 | <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/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. |
Added www/whyallinone.md.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | # Why Add Forum, Wiki, and Web Software To Your DVCS? One notable feature of Fossil is that it bundles [bug tracking](./bugtheory.wiki), [wiki](./wikitheory.wiki), [forum](./forum.wiki), [chat](./chat.md), and [technotes](./event.wiki) with distributed version control to give you an all-in-one software project management system. A commenter on [Hacker News](https://news.ycombinator.com/item?id=27437895) takes exception to this idea, writing: > *I don't want forum/web software built into my dvcs.* > *I don't see how this improves over git.* This commenter may hold whatever opinions he wishes, of course. However, there are many good reasons why bundling other project management features with the DVCS might be useful for a given project: 1. There is a single software package to install and manage for the project website. The alternative is to select, install, configure, learn about, manage, and maintain separate DVCS, wiki, ticketing, forum, chat, documentation, and whatever other software packages your project needs. Less time spent on project administration details means more time available to spend on the project itself. 2. Fossil’s autosync feature gives you an implicit backup of the wiki, tickets, forum, and so forth simply by cloning the repository to another machine and using that clone regularly. Since the typical Fossil usage pattern is to stand the repo up on a central server and have the developers clone that repository down to their personal machines, if the server falls over, the last developer to do anything that resulted in an autosync has a functional and up-to-date backup. There are [limitations to relying on Fossil’s autosync feature for backup purposes](./backup.md), but that document gives two methods for more complete backups, both of which are easily automated. The Fossil project itself is distributed across three data centers in this manner via cron. 3. Remote workers get more than just the source code: they get the entire website including versioned documentation, wiki articles, tickets, forum posts, and so forth. This supports off-network development when traveling, when riding out Internet service failures, and when workers must sync with multiple remote servers, as when working alternately from home and in some central office. Feature-competitive Fossil alternatives typically solve this same problem with centralization, which generally means that only the DVCS piece still works in these situations where the developer is unable to contact the central server. Why accept the limitation of having a distributed clone of the code repo alone? Centralization doesn’t work for every project. If you enjoy the benefits of truly distributed (read: non-centralized) version control, you may also benefit from distributed forums, distributed ticket tracking, distributed wiki article publishing, and so forth. 4. Integration of all of these features allows easy hyperlinks between check-in comments, wiki pages, forum posts, and tickets. More, because the software sees both sides of the link, referrer and referent, it can provide automatic back-references. A common situation in a Fossil project is that: * a forum post refers to a versioned project document that shows that the software isn’t behaving as documented; * a developer triages that forum report as a verified bug, filing a ticket to prioritize and track the resolution; * developers chat about the problem, referring to the ticket and thereby indirectly referring to the forum post, plus perhaps to other Fossil-managed resources such as a wiki document giving design principles that guide the proper fix; and finally * the commit message resolving the ticket includes a reference to the ticket it resolves. Since Fossil sees that the commit refers to a ticket, the ticket page automatically also refers back to the commit, closing the loop. A latecomer may arrive at the ticket via a web search, and from that see that it was closed following a commit. They can follow the link from the initial ticket message to the forum thread to catch up on the discussion leading to the fix and likely find a follow-up post from the initial reporting user saying whether the fix worked for them. If further work was needed, the latecomer can likely find it from that forum thread. This works even in a remote off-network clone: the developer can pull up the project web site via an `http://localhost` link and follow these links around the loop. Fossil allows breaking some of these project facilities out into separate repositories, as when the public forum is kept separate from the actual software development repository for administration reasons. By using Fossil’s [interwiki link feature](./interwiki.md), you can get this same internal linking from ticket to commit to forum to wiki even across these administrative boundaries, even with remote off-network clones, simply by adjusting the interwiki map to match the remote clone’s network configuration. 5. Bundling all of these services gives [single sign-on][SSO] (SSO) for all aspects of the project. The same username/password works for code, wiki, forum, tickets, and chat. If you choose to administratively separate some of these features by setting up multiple cooperating Fossil repositories, its [login groups feature](./caps/login-groups.md) allows asymmetric SSO across these administrative boundaries so that, for example, users allowed to commit to the code repository also get a forum repository login, but self-registered forum users don’t automatically get the ability to commit to the code repo. 6. Bundling all of these features reduces the number of external dependencies for the project. Take the first two points above: standing up a Fossil repo backup on a new server may be as simple as copying the backup to the new server and [configuring its stock HTTP server to point at the backup repository via CGI](./server/any/cgi.md). Consider: If you had good backups for all of the elements in a Git + [Jira] + [Discord] + [MediaWiki] + [Sphinx] lash-up, how long would it take you to stand up a replacement? That lash-up certainly has more features combined than Fossil alone, but are they worth the administration and hosting costs they impose? Fossil’s feature set suffices for the SQLite project it was created to serve, as well as for many others; is your project sufficiently more complex, such that it *needs* all of those extra features and their concomitant complexity? Considerations such as these push many into centralized hosting services such as GitHub, GitLab, Bitbucket, and so forth, but that just takes you back to point 3 above. 7. Hosting all of these elements within a single service gives a consistent look-and-feel across all aspects of the project. Skinning independent software packages’ web interfaces to make them appear unified is more work than skinning everything once, as in Fossil, and even then, you can’t make independently-developed software look like it was produced by a single entity without resorting to heroic levels of customization. If you use a separate DVCS web front end, chat system, forum manager, documentation system, ticket tracker, and so on, you are likely to be relegated to simply matching colors and fonts; you *might* also get the ability to add a common logo to the header of all of these independent pieces. The pieces won’t look unified, because they weren’t developed that way. The Fossil project’s skinning system lets you affect all of its elements globally from the single skin editor. Or not: there’s a feature in Fossil that lets skin customizations apply to only *some* Fossil features. The initial impetus behind this feature was that one of our users wanted Markdown to be rendered with different indentation in forum posts than in [embedded documentation][edoc] owing to the inherent differences between the two presentation modalities. A user taking advantage of this per-feature CSS capability who wishes to change a UI element common to all Fossil features — say, to change the font for literal code blocks — may still make such a change globally. Opting into this per-feature CSS doesn’t fork all skinning efforts: UI elements not explicitly reskinned on a per-feature basis inherit the global skinning. But it goes futher. Fossil has a feature for [project-specific extensions](./serverext.wiki), which backs the [SQLite Release Checklist][srckl], for instance. You wouldn’t know by looking at that page that it’s produced by software that isn’t actually part of Fossil: the extension only delivers the core of the page, and Fossil’s skining wraps it in a way that lets it inherit all of the project-level skinning customizations. 8. Unifying all of these features within Fossil means we have a single Markdown interpreter common to all elements. If you lash multiple software systems together, even if they can all agree on Markdown as a common document markup language — hardly a given, as shown by the MediaWiki and Sphinx elements in point 6’s example above — they’re likely to render your text using different — possibly even incompatibly-different — Markdown dialects. This costs you in mental gear-switching when moving from the code repository to the documentation system to the forums to the ticket tracker. More than that, though, a developer might write a forum post that later gets promoted to a wiki article or to an embedded version-controlled project document. A developer on a Fossil-backed project may simply copy-paste the forum post text into the new document and save it, not needing to carefully check that it still renders properly under the second Markdown rendering engine. Similarly, if a user reports a potential bug via the forum, the developer can copy interesting pieces of the Markdown from the post into a ticket comment, again without needing to fiddle with dialect incompatibilities. 9. Fossil is [free, open-source software](../COPYRIGHT-BSD2.txt), through and through. Git-backed lash-ups tend to incorporate either proprietary add-ons or proprietary hosting systems that produce vendor lock-in. Fossil gives you the freedom to take your complete backup (point 2) of the project including its idiosyncratic customizations and stand it up elsewhere on commodity hardware and software stacks. All of this having been said, the non-DVCS features of Fossil are optional. Its forum and chat features are disabled by default, and you can disable the ticket-tracking and wiki features with a quick configuration change to its [role-based access control system](./caps/). When you’re ready to turn these additional features on, you can do so with a few mouse clicks. Because Fossil is web-native out of the box, if you’ve delegated these features to outside systems to flesh out Git’s DVCS-only nature, Fossil can link out to these systems, and they back into Fossil, letting you use Fossil in the same DVCS-only mode. [Discord]: https://discord.com/ [edoc]: ./embeddeddoc.wiki [Jira]: https://www.atlassian.com/software/jira [MediaWiki]: https://www.mediawiki.org/ [Sphinx]: https://www.sphinx-doc.org/en/master/ [SSO]: https://en.wikipedia.org/wiki/Single_sign-on [srckl]: https://www.sqlite.org/src/ext/checklist/top/index |