Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merge from trunk |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | wcontent-subsets |
| Files: | files | file ages | folders |
| SHA3-256: |
cea36e6c866da8baa31359787482af4d |
| User & Date: | george 2021-06-15 21:37:18.130 |
Context
|
2021-08-15
| ||
| 23:27 | Merge from trunk check-in: 282c6f956f user: george tags: wcontent-subsets | |
|
2021-06-15
| ||
| 21:37 | Merge from trunk check-in: cea36e6c86 user: george tags: wcontent-subsets | |
| 17:20 | Factored out an extraneous var from [1bb06c94]. No functional changes. check-in: e0686dda41 user: stephan tags: trunk | |
|
2021-04-21
| ||
| 20:53 | Enable interactive adjustment of the set of wiki pages that are listed on the [/wcontent] page. Corresponding submenu controls can be configured by the administrator to fulfill local needs and constraints. check-in: 7971343314 user: george tags: wcontent-subsets | |
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.
| ︙ | ︙ | |||
211 212 213 214 215 216 217 | } /* 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. |
| ︙ | ︙ | |||
481 482 483 484 485 486 487 |
** 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
|
| ︙ | ︙ |
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);
|
| ︙ | ︙ | |||
734 735 736 737 738 739 740 741 742 743 744 745 746 747 |
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);
|
| ︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 |
},
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;
|
| ︙ | ︙ | |||
1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 |
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/forum.c.
| ︙ | ︙ | |||
544 545 546 547 548 549 550 |
@ 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()
|
| ︙ | ︙ | |||
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 |
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);
}
|
| ︙ | ︙ | |||
1294 1295 1296 1297 1298 1299 1300 |
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 |
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) ){
|
| ︙ | ︙ |
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.wcontent.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.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.wcontent.js \ $(SRCDIR)/fossil.page.whistory.js \ $(SRCDIR)/fossil.page.wikiedit.js \ $(SRCDIR)/fossil.pikchr.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.
| ︙ | ︙ | |||
400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
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( !dryRunFlag ){
if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
db_get_int("autosync-tries", 1), 1) ){
fossil_fatal("merge abandoned due to sync failure");
}
}
| > > > | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
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");
}
}
|
| ︙ | ︙ | |||
616 617 618 619 620 621 622 623 624 625 |
** (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 fn=vfile.pathname FROM vfile"
" WHERE fn IS NULL"
| > > > > > > > | > > > > > > > | > > > > > > > | | 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 |
** (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);
|
| ︙ | ︙ | |||
700 701 702 703 704 705 706 |
*/
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(
| | | | | | | | > > | < < | | 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 |
*/
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"
|
| ︙ | ︙ |
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, |
| ︙ | ︙ | |||
238 239 240 241 242 243 244 |
break;
}
}
return rc;
}
/*
| | > | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
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();
|
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
zSql = mprintf("SELECT * FROM (%s) ORDER BY %d %s", zSql, nField, zDir);
}
}
count = 0;
if( !tabs ){
struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
db_multi_exec("PRAGMA empty_result_callbacks=ON");
style_set_current_feature("report");
| > > > > > > | > > | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 |
zSql = mprintf("SELECT * FROM (%s) ORDER BY %d %s", zSql, nField, zDir);
}
}
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.
| ︙ | ︙ | |||
4961 4962 4963 4964 4965 4966 4967 |
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
|
| ︙ | ︙ | |||
5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 | } 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:
|
| ︙ | ︙ | |||
5916 5917 5918 5919 5920 5921 5922 5923 5924 | #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)) |
| ︙ | ︙ | |||
6586 6587 6588 6589 6590 6591 6592 |
** 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.
*/
|
| ︙ | ︙ | |||
8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 |
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
|
| ︙ | ︙ | |||
14030 14031 14032 14033 14034 14035 14036 | " -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()", |
| ︙ | ︙ | |||
14132 14133 14134 14135 14136 14137 14138 | " -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", |
| ︙ | ︙ | |||
14454 14455 14456 14457 14458 14459 14460 |
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;
|
| ︙ | ︙ | |||
14543 14544 14545 14546 14547 14548 14549 |
}
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.
*/
|
| ︙ | ︙ | |||
14769 14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 14781 14782 |
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);
|
| ︙ | ︙ | |||
14804 14805 14806 14807 14808 14809 14810 |
#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);
|
| ︙ | ︙ | |||
16871 16872 16873 16874 16875 16876 16877 16878 16879 16880 16881 16882 16883 16884 |
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.
*/
|
| ︙ | ︙ | |||
17892 17893 17894 17895 17896 17897 17898 |
}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
|
| ︙ | ︙ | |||
17918 17919 17920 17921 17922 17923 17924 |
/* 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);
}
|
| ︙ | ︙ | |||
18175 18176 18177 18178 18179 18180 18181 |
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;
|
| ︙ | ︙ | |||
18197 18198 18199 18200 18201 18202 18203 |
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]);
|
| ︙ | ︙ | |||
18866 18867 18868 18869 18870 18871 18872 |
#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;
|
| ︙ | ︙ | |||
20111 20112 20113 20114 20115 20116 20117 20118 20119 20120 20121 20122 20123 20124 |
{ "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;
|
| ︙ | ︙ | |||
20255 20256 20257 20258 20259 20260 20261 |
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 ){
|
| ︙ | ︙ | |||
20857 20858 20859 20860 20861 20862 20863 | " -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 |
| ︙ | ︙ | |||
21204 21205 21206 21207 21208 21209 21210 |
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;
|
| ︙ | ︙ | |||
21321 21322 21323 21324 21325 21326 21327 |
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.
| ︙ | ︙ | |||
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),
|
| ︙ | ︙ | |||
1184 1185 1186 1187 1188 1189 1190 | ** ** 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 | | | 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 | ** ** 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 |
| ︙ | ︙ | |||
2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 | ** 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> */ #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 | > > > > | 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 | ** 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 |
| ︙ | ︙ | |||
2239 2240 2241 2242 2243 2244 2245 | #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 | < > | 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 |
| ︙ | ︙ | |||
5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 | ** 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 ** |
| ︙ | ︙ | |||
5422 5423 5424 5425 5426 5427 5428 | ** 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 |
| ︙ | ︙ | |||
6175 6176 6177 6178 6179 6180 6181 | ** 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 |
| ︙ | ︙ | |||
8853 8854 8855 8856 8857 8858 8859 | #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, |
| ︙ | ︙ | |||
10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625 10626 10627 10628 10629 10630 10631 10632 10633 10634 10635 10636 10637 10638 |
**
** ^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
|
| ︙ | ︙ | |||
10863 10864 10865 10866 10867 10868 10869 | ** 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 */ ); |
| ︙ | ︙ | |||
10915 10916 10917 10918 10919 10920 10921 | ** 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[] */ |
| ︙ | ︙ | |||
11165 11166 11167 11168 11169 11170 11171 11172 11173 11174 11175 11176 11177 11178 | ** ** 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 |
| ︙ | ︙ | |||
11409 11410 11411 11412 11413 11414 11415 11416 11417 11418 11419 11420 11421 11422 | */ 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 |
| ︙ | ︙ | |||
14233 14234 14235 14236 14237 14238 14239 | #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> |
| ︙ | ︙ | |||
15929 15930 15931 15932 15933 15934 15935 | /* 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,} | | | 16023 16024 16025 16026 16027 16028 16029 16030 16031 16032 16033 16034 16035 16036 16037 | /* 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 */ |
| ︙ | ︙ | |||
16461 16462 16463 16464 16465 16466 16467 16468 16469 16470 16471 16472 16473 16474 | /* 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 |
| ︙ | ︙ | |||
17217 17218 17219 17220 17221 17222 17223 | #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) |
| ︙ | ︙ | |||
17722 17723 17724 17725 17726 17727 17728 17729 17730 17731 17732 17733 17734 17735 |
** 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
|
| ︙ | ︙ | |||
18434 18435 18436 18437 18438 18439 18440 18441 18442 18443 18444 18445 18446 18447 |
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 */
|
| ︙ | ︙ | |||
18551 18552 18553 18554 18555 18556 18557 |
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.
**
|
| ︙ | ︙ | |||
18584 18585 18586 18587 18588 18589 18590 18591 18592 18593 18594 18595 18596 18597 | #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 |
| ︙ | ︙ | |||
18696 18697 18698 18699 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 | #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 |
| ︙ | ︙ | |||
19224 19225 19226 19227 19228 19229 19230 19231 19232 19233 19234 19235 19236 19237 |
/*
** 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 */
|
| ︙ | ︙ | |||
19278 19279 19280 19281 19282 19283 19284 | #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 ); |
| ︙ | ︙ | |||
19365 19366 19367 19368 19369 19370 19371 19372 19373 19374 19375 19376 19377 19378 19379 19380 19381 19382 | 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 */ |
| ︙ | ︙ | |||
19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 |
/*
** 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
|
| ︙ | ︙ | |||
19795 19796 19797 19798 19799 19800 19801 19802 19803 19804 19805 19806 19807 19808 | 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 |
| ︙ | ︙ | |||
20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 20041 20042 20043 | 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*, |
| ︙ | ︙ | |||
20173 20174 20175 20176 20177 20178 20179 | 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*); |
| ︙ | ︙ | |||
20440 20441 20442 20443 20444 20445 20446 | 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 |
| ︙ | ︙ | |||
20935 20936 20937 20938 20939 20940 20941 | 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 */ |
| ︙ | ︙ | |||
21498 21499 21500 21501 21502 21503 21504 21505 21506 21507 21508 21509 21510 21511 | 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 */ }; |
| ︙ | ︙ | |||
21541 21542 21543 21544 21545 21546 21547 | 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*)); |
| ︙ | ︙ | |||
21586 21587 21588 21589 21590 21591 21592 | #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 *);
|
| ︙ | ︙ | |||
23537 23538 23539 23540 23541 23542 23543 23544 23545 23546 23547 23548 23549 23550 |
){
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);
|
| ︙ | ︙ | |||
27804 27805 27806 27807 27808 27809 27810 |
** 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);
|
| ︙ | ︙ | |||
29930 29931 29932 29933 29934 29935 29936 29937 29938 29939 29940 29941 29942 29943 |
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);
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");
| > | 30067 30068 30069 30070 30071 30072 30073 30074 30075 30076 30077 30078 30079 30080 30081 |
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");
|
| ︙ | ︙ | |||
30500 30501 30502 30503 30504 30505 30506 30507 30508 30509 30510 30511 30512 30513 |
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 ){
|
| ︙ | ︙ | |||
41970 41971 41972 41973 41974 41975 41976 41977 41978 41979 41980 41981 41982 41983 |
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,
|
| ︙ | ︙ | |||
48363 48364 48365 48366 48367 48368 48369 | ** 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);
|
| ︙ | ︙ | |||
48441 48442 48443 48444 48445 48446 48447 | 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 */
|
| ︙ | ︙ | |||
48466 48467 48468 48469 48470 48471 48472 48473 48474 48475 48476 | 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,
|
| ︙ | ︙ | |||
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 |
*/
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.
*/
|
| ︙ | ︙ | |||
48804 48805 48806 48807 48808 48809 48810 48811 48812 48813 48814 48815 48816 48817 48818 48819 48820 |
/*
** 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(
|
| ︙ | ︙ | |||
48842 48843 48844 48845 48846 48847 48848 |
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);
|
| ︙ | ︙ | |||
48941 48942 48943 48944 48945 48946 48947 |
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
|
| ︙ | ︙ | |||
56893 56894 56895 56896 56897 56898 56899 |
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 */
|
| ︙ | ︙ | |||
57097 57098 57099 57100 57101 57102 57103 |
/* 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:
|
| ︙ | ︙ | |||
58065 58066 58067 58068 58069 58070 58071 |
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) ){
|
| ︙ | ︙ | |||
60939 60940 60941 60942 60943 60944 60945 |
** 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++){
|
| ︙ | ︙ | |||
65585 65586 65587 65588 65589 65590 65591 |
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;
|
| ︙ | ︙ | |||
66486 66487 66488 66489 66490 66491 66492 66493 66494 66495 66496 66497 66498 66499 | 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; |
| ︙ | ︙ | |||
66527 66528 66529 66530 66531 66532 66533 |
}
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:
|
| ︙ | ︙ | |||
71457 71458 71459 71460 71461 71462 71463 |
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);
|
| ︙ | ︙ | |||
71530 71531 71532 71533 71534 71535 71536 71537 71538 71539 71540 71541 71542 71543 |
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[].
|
| ︙ | ︙ | |||
72053 72054 72055 72056 72057 72058 72059 |
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];
}
}
|
| ︙ | ︙ | |||
72207 72208 72209 72210 72211 72212 72213 |
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++;
}
}
|
| ︙ | ︙ | |||
72860 72861 72862 72863 72864 72865 72866 |
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
|
| ︙ | ︙ | |||
73183 73184 73185 73186 73187 73188 73189 73190 73191 73192 73193 73194 73195 73196 |
}
/* 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;
|
| ︙ | ︙ | |||
73226 73227 73228 73229 73230 73231 73232 73233 73234 73235 73236 73237 73238 73239 |
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
|
| ︙ | ︙ | |||
73768 73769 73770 73771 73772 73773 73774 73775 73776 73777 73778 73779 73780 |
** 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 );
|
| ︙ | ︙ | |||
73855 73856 73857 73858 73859 73860 73861 |
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;
}
|
| ︙ | ︙ | |||
73909 73910 73911 73912 73913 73914 73915 |
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
|
| ︙ | ︙ | |||
74146 74147 74148 74149 74150 74151 74152 |
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 |
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);
|
| ︙ | ︙ | |||
74201 74202 74203 74204 74205 74206 74207 |
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
|
| ︙ | ︙ | |||
74497 74498 74499 74500 74501 74502 74503 |
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);
|
| ︙ | ︙ | |||
74529 74530 74531 74532 74533 74534 74535 | ** 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;
}
/*
|
| ︙ | ︙ | |||
76628 76629 76630 76631 76632 76633 76634 |
}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
|
| ︙ | ︙ | |||
76792 76793 76794 76795 76796 76797 76798 | /* 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;
|
| ︙ | ︙ | |||
77621 77622 77623 77624 77625 77626 77627 | ** 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. */
|
| ︙ | ︙ | |||
77647 77648 77649 77650 77651 77652 77653 |
}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 );
|
| ︙ | ︙ | |||
77685 77686 77687 77688 77689 77690 77691 |
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.
|
| ︙ | ︙ | |||
83650 83651 83652 83653 83654 83655 83656 | 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;
|
| ︙ | ︙ | |||
83686 83687 83688 83689 83690 83691 83692 83693 83694 83695 83696 83697 83698 83699 | 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); |
| ︙ | ︙ | |||
84099 84100 84101 84102 84103 84104 84105 |
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 *)
|
| ︙ | ︙ | |||
85081 85082 85083 85084 85085 85086 85087 | /* ** 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;
|
| ︙ | ︙ | |||
85133 85134 85135 85136 85137 85138 85139 |
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);
|
| ︙ | ︙ | |||
85207 85208 85209 85210 85211 85212 85213 |
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,
|
| ︙ | ︙ | |||
85611 85612 85613 85614 85615 85616 85617 85618 85619 85620 85621 85622 85623 85624 |
** 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){
|
| ︙ | ︙ | |||
86233 86234 86235 86236 86237 86238 86239 |
(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
|
| ︙ | ︙ | |||
86391 86392 86393 86394 86395 86396 86397 |
** 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;
|
| ︙ | ︙ | |||
86528 86529 86530 86531 86532 86533 86534 86535 86536 86537 86538 86539 86540 86541 |
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.
|
| ︙ | ︙ | |||
88065 88066 88067 88068 88069 88070 88071 88072 88073 88074 88075 88076 88077 88078 |
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.
*/
|
| ︙ | ︙ | |||
88095 88096 88097 88098 88099 88100 88101 |
VdbeBranchTaken(2,3);
if( pOp->p5 & SQLITE_JUMPIFNULL ){
goto jump_to_p2;
}
break;
}
}else{
| | > < < < < < < < < | 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 |
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) );
|
| ︙ | ︙ | |||
88138 88139 88140 88141 88142 88143 88144 |
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 |
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 );
|
| ︙ | ︙ | |||
90579 90580 90581 90582 90583 90584 90585 90586 90587 90588 90589 90590 90591 90592 90593 90594 |
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
|
| ︙ | ︙ | |||
90695 90696 90697 90698 90699 90700 90701 90702 90703 90704 90705 90706 90707 90708 |
** 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 */
|
| ︙ | ︙ | |||
91124 91125 91126 91127 91128 91129 91130 |
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;
|
| ︙ | ︙ | |||
91284 91285 91286 91287 91288 91289 91290 |
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 );
|
| ︙ | ︙ | |||
92230 92231 92232 92233 92234 92235 92236 | ** 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;
}
|
| ︙ | ︙ | |||
92353 92354 92355 92356 92357 92358 92359 |
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;
|
| ︙ | ︙ | |||
93235 93236 93237 93238 93239 93240 93241 93242 93243 93244 93245 93246 93247 93248 | 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 |
| ︙ | ︙ | |||
94713 94714 94715 94716 94717 94718 94719 |
** 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 ){
|
| ︙ | ︙ | |||
94784 94785 94786 94787 94788 94789 94790 94791 94792 94793 94794 94795 94796 94797 |
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 );
}
|
| ︙ | ︙ | |||
98254 98255 98256 98257 98258 98259 98260 |
}
/*
** 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){
|
| ︙ | ︙ | |||
98466 98467 98468 98469 98470 98471 98472 |
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
/*
|
| ︙ | ︙ | |||
98550 98551 98552 98553 98554 98555 98556 98557 98558 98559 98560 98561 98562 98563 98564 98565 98566 98567 98568 98569 98570 |
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
|
| ︙ | ︙ | |||
98591 98592 98593 98594 98595 98596 98597 |
*/
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)
){
|
| ︙ | ︙ | |||
98765 98766 98767 98768 98769 98770 98771 | 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,
|
| ︙ | ︙ | |||
98787 98788 98789 98790 98791 98792 98793 |
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);
}
}
|
| ︙ | ︙ | |||
99182 99183 99184 99185 99186 99187 99188 |
**
** 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
|
| ︙ | ︙ | |||
99291 99292 99293 99294 99295 99296 99297 |
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.
**
|
| ︙ | ︙ | |||
99598 99599 99600 99601 99602 99603 99604 |
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
|
| ︙ | ︙ | |||
99620 99621 99622 99623 99624 99625 99626 |
#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) ){
|
| ︙ | ︙ | |||
99676 99677 99678 99679 99680 99681 99682 |
|| (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
|
| ︙ | ︙ | |||
99941 99942 99943 99944 99945 99946 99947 | /* 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. |
| ︙ | ︙ | |||
100044 100045 100046 100047 100048 100049 100050 |
/* 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;
|
| ︙ | ︙ | |||
100201 100202 100203 100204 100205 100206 100207 |
){
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' ){
|
| ︙ | ︙ | |||
100291 100292 100293 100294 100295 100296 100297 100298 100299 100300 100301 100302 100303 100304 100305 |
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;
|
| ︙ | ︙ | |||
100366 100367 100368 100369 100370 100371 100372 |
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;
|
| ︙ | ︙ | |||
100424 100425 100426 100427 100428 100429 100430 |
** 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;
}
|
| ︙ | ︙ | |||
100452 100453 100454 100455 100456 100457 100458 |
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;
}
|
| ︙ | ︙ | |||
100548 100549 100550 100551 100552 100553 100554 | 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.
*/
|
| ︙ | ︙ | |||
100612 100613 100614 100615 100616 100617 100618 |
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
|
| ︙ | ︙ | |||
100755 100756 100757 100758 100759 100760 100761 100762 100763 100764 100765 100766 100767 100768 |
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 ){
|
| ︙ | ︙ | |||
100798 100799 100800 100801 100802 100803 100804 |
*/
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;
}
}
|
| ︙ | ︙ | |||
101159 101160 101161 101162 101163 101164 101165 |
**
** 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;
}
|
| ︙ | ︙ | |||
101275 101276 101277 101278 101279 101280 101281 |
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.
**
|
| ︙ | ︙ | |||
101344 101345 101346 101347 101348 101349 101350 |
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;
| | | 101845 101846 101847 101848 101849 101850 101851 101852 101853 101854 101855 101856 101857 101858 101859 |
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);
|
| ︙ | ︙ | |||
102027 102028 102029 102030 102031 102032 102033 102034 102035 102036 102037 102038 102039 102040 |
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 ){
|
| ︙ | ︙ | |||
102105 102106 102107 102108 102109 102110 102111 |
*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
|
| ︙ | ︙ | |||
102220 102221 102222 102223 102224 102225 102226 |
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 ){
| | > | 102723 102724 102725 102726 102727 102728 102729 102730 102731 102732 102733 102734 102735 102736 102737 102738 |
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;
|
| ︙ | ︙ | |||
102343 102344 102345 102346 102347 102348 102349 |
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;
}
|
| ︙ | ︙ | |||
103050 103051 103052 103053 103054 103055 103056 103057 103058 103059 103060 103061 103062 103063 103064 103065 |
** 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:
|
| ︙ | ︙ | |||
103683 103684 103685 103686 103687 103688 103689 103690 103691 103692 103693 103694 103695 103696 |
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(
|
| ︙ | ︙ | |||
103794 103795 103796 103797 103798 103799 103800 103801 103802 103803 103804 103805 103806 103807 103808 103809 103810 103811 103812 103813 103814 103815 103816 103817 |
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.
**
|
| ︙ | ︙ | |||
103875 103876 103877 103878 103879 103880 103881 103882 103883 103884 103885 103886 103887 |
}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;
|
| ︙ | ︙ | |||
104718 104719 104720 104721 104722 104723 104724 |
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;
|
| ︙ | ︙ | |||
105061 105062 105063 105064 105065 105066 105067 |
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;
|
| ︙ | ︙ | |||
106693 106694 106695 106696 106697 106698 106699 106700 106701 106702 106703 106704 106705 106706 |
&& 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[]
*/
|
| ︙ | ︙ | |||
106893 106894 106895 106896 106897 106898 106899 106900 106901 106902 106903 106904 106905 106906 |
** 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;
|
| ︙ | ︙ | |||
107661 107662 107663 107664 107665 107666 107667 107668 107669 107670 107671 107672 |
/*
** 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.
*/
|
| ︙ | ︙ | |||
107696 107697 107698 107699 107700 107701 107702 |
/*
** 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);
}
}
|
| ︙ | ︙ | |||
107780 107781 107782 107783 107784 107785 107786 |
*/
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;
|
| ︙ | ︙ | |||
107802 107803 107804 107805 107806 107807 107808 |
/*
** 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.
**
|
| ︙ | ︙ | |||
108332 108333 108334 108335 108336 108337 108338 |
}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);
}
|
| ︙ | ︙ | |||
108436 108437 108438 108439 108440 108441 108442 |
/*
** 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);
|
| ︙ | ︙ | |||
108981 108982 108983 108984 108985 108986 108987 |
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;
}
| > > > | > > | 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 |
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);
|
| ︙ | ︙ | |||
111061 111062 111063 111064 111065 111066 111067 | 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
|
| ︙ | ︙ | |||
111430 111431 111432 111433 111434 111435 111436 |
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
}
|
| ︙ | ︙ | |||
111477 111478 111479 111480 111481 111482 111483 | 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 |
| ︙ | ︙ | |||
111539 111540 111541 111542 111543 111544 111545 |
|| 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;
|
| ︙ | ︙ | |||
111878 111879 111880 111881 111882 111883 111884 | ** 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;
}
|
| ︙ | ︙ | |||
111916 111917 111918 111919 111920 111921 111922 111923 111924 111925 111926 111927 111928 111929 |
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;
|
| ︙ | ︙ | |||
112270 112271 112272 112273 112274 112275 112276 |
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;
}
|
| ︙ | ︙ | |||
112293 112294 112295 112296 112297 112298 112299 112300 112301 112302 112303 112304 112305 112306 |
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.
|
| ︙ | ︙ | |||
112709 112710 112711 112712 112713 112714 112715 |
*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;
}
|
| ︙ | ︙ | |||
112877 112878 112879 112880 112881 112882 112883 112884 112885 112886 112887 112888 112889 112890 |
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
|
| ︙ | ︙ | |||
112977 112978 112979 112980 112981 112982 112983 112984 112985 112986 112987 112988 112989 112990 |
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;
}
|
| ︙ | ︙ | |||
113153 113154 113155 113156 113157 113158 113159 113160 113161 113162 113163 113164 113165 113166 | 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) |
| ︙ | ︙ | |||
114011 114012 114013 114014 114015 114016 114017 |
*/
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 );
/*
|
| ︙ | ︙ | |||
114224 114225 114226 114227 114228 114229 114230 |
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;
}
|
| ︙ | ︙ | |||
114472 114473 114474 114475 114476 114477 114478 114479 114480 114481 114482 114483 114484 114485 |
/* 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;
| > | 115074 115075 115076 115077 115078 115079 115080 115081 115082 115083 115084 115085 115086 115087 115088 |
/* 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;
|
| ︙ | ︙ | |||
115020 115021 115022 115023 115024 115025 115026 |
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.
|
| ︙ | ︙ | |||
115590 115591 115592 115593 115594 115595 115596 115597 115598 115599 115600 115601 115602 115603 |
}
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;
|
| ︙ | ︙ | |||
116070 116071 116072 116073 116074 116075 116076 |
** 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) );
|
| ︙ | ︙ | |||
116108 116109 116110 116111 116112 116113 116114 116115 116116 116117 116118 116119 116120 116121 116122 116123 116124 116125 116126 116127 116128 116129 116130 116131 116132 116133 |
}
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);
}
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;
}
| > | | 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 |
}
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 */
|
| ︙ | ︙ | |||
116419 116420 116421 116422 116423 116424 116425 |
/*
** 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);
}
}
|
| ︙ | ︙ | |||
118145 118146 118147 118148 118149 118150 118151 118152 118153 118154 118155 118156 118157 118158 |
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);
|
| ︙ | ︙ | |||
118656 118657 118658 118659 118660 118661 118662 |
&& 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;
}
|
| ︙ | ︙ | |||
120757 120758 120759 120760 120761 120762 120763 | 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 );
|
| ︙ | ︙ | |||
122789 122790 122791 122792 122793 122794 122795 |
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;
}
|
| ︙ | ︙ | |||
126822 126823 126824 126825 126826 126827 126828 | 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"
|
| ︙ | ︙ | |||
126856 126857 126858 126859 126860 126861 126862 126863 126864 126865 126866 126867 126868 126869 126870 126871 |
*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 ".",
|
| ︙ | ︙ | |||
126912 126913 126914 126915 126916 126917 126918 |
}
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;
|
| ︙ | ︙ | |||
126949 126950 126951 126952 126953 126954 126955 126956 126957 126958 126959 126960 126961 126962 |
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 */
){
|
| ︙ | ︙ | |||
130508 130509 130510 130511 130512 130513 130514 130515 130516 130517 130518 130519 130520 130521 |
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
|
| ︙ | ︙ | |||
130789 130790 130791 130792 130793 130794 130795 130796 130797 130798 |
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
|
| ︙ | ︙ | |||
133385 133386 133387 133388 133389 133390 133391 | ** 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;
|
| ︙ | ︙ | |||
133475 133476 133477 133478 133479 133480 133481 | ** 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 */
){
|
| ︙ | ︙ | |||
134178 134179 134180 134181 134182 134183 134184 134185 134186 134187 134188 134189 134190 134191 134192 134193 134194 134195 134196 134197 134198 134199 134200 134201 134202 134203 134204 134205 134206 134207 134208 |
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;
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"));
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)
| > > | 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 |
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)
|
| ︙ | ︙ | |||
134247 134248 134249 134250 134251 134252 134253 134254 134255 134256 134257 134258 134259 134260 134261 134262 134263 134264 134265 134266 134267 134268 134269 134270 134271 134272 134273 134274 134275 134276 134277 134278 134279 |
}
/* 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 ){
|
| ︙ | ︙ | |||
134326 134327 134328 134329 134330 134331 134332 134333 134334 134335 134336 134337 134338 134339 134340 134341 134342 134343 134344 134345 134346 134347 134348 134349 134350 134351 134352 134353 134354 134355 |
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;
}
|
| ︙ | ︙ | |||
134974 134975 134976 134977 134978 134979 134980 134981 134982 134983 134984 134985 134986 134987 |
/* 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
|
| ︙ | ︙ | |||
135054 135055 135056 135057 135058 135059 135060 |
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
| > > > > | | < | | | | | | | < | 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 |
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);
|
| ︙ | ︙ | |||
135192 135193 135194 135195 135196 135197 135198 |
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);
}
}
}
}
|
| ︙ | ︙ | |||
135632 135633 135634 135635 135636 135637 135638 |
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"
|
| ︙ | ︙ | |||
135831 135832 135833 135834 135835 135836 135837 135838 135839 135840 135841 135842 135843 135844 135845 135846 |
/*
** 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.
**
|
| ︙ | ︙ | |||
135871 135872 135873 135874 135875 135876 135877 135878 135879 135880 135881 135882 135883 135884 135885 135886 135887 135888 135889 135890 135891 135892 135893 135894 135895 135896 135897 |
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
|
| ︙ | ︙ | |||
135978 135979 135980 135981 135982 135983 135984 135985 135986 135987 135988 135989 135990 135991 135992 135993 135994 135995 135996 135997 135998 135999 136000 136001 136002 136003 136004 |
** 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;
|
| ︙ | ︙ | |||
136427 136428 136429 136430 136431 136432 136433 136434 136435 136436 136437 136438 136439 136440 136441 136442 |
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
|
| ︙ | ︙ | |||
136481 136482 136483 136484 136485 136486 136487 136488 136489 136490 136491 136492 136493 136494 136495 136496 136497 136498 136499 |
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;
|
| ︙ | ︙ | |||
136532 136533 136534 136535 136536 136537 136538 136539 136540 136541 136542 136543 136544 136545 |
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;
}
|
| ︙ | ︙ | |||
136635 136636 136637 136638 136639 136640 136641 | ** 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,
|
| ︙ | ︙ | |||
136733 136734 136735 136736 136737 136738 136739 136740 136741 136742 136743 136744 136745 136746 |
}
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);
|
| ︙ | ︙ | |||
136793 136794 136795 136796 136797 136798 136799 136800 136801 136802 136803 136804 136805 136806 |
&& (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);
|
| ︙ | ︙ | |||
137033 137034 137035 137036 137037 137038 137039 |
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
/*
|
| ︙ | ︙ | |||
137620 137621 137622 137623 137624 137625 137626 |
);
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);
|
| ︙ | ︙ | |||
137751 137752 137753 137754 137755 137756 137757 | #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);
|
| ︙ | ︙ | |||
137814 137815 137816 137817 137818 137819 137820 |
#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.
|
| ︙ | ︙ | |||
137913 137914 137915 137916 137917 137918 137919 |
** 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 |
** 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. */
|
| ︙ | ︙ | |||
138342 138343 138344 138345 138346 138347 138348 |
** 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
);
| > | | > | 139070 139071 139072 139073 139074 139075 139076 139077 139078 139079 139080 139081 139082 139083 139084 139085 139086 139087 |
** 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
*/
|
| ︙ | ︙ | |||
138476 138477 138478 138479 138480 138481 138482 138483 138484 138485 138486 138487 138488 138489 |
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlite3WhereEnd(pWInfo);
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
/* Output the final row of result
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output final row"));
/* Jump over the subroutines
| > | 139206 139207 139208 139209 139210 139211 139212 139213 139214 139215 139216 139217 139218 139219 139220 |
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
|
| ︙ | ︙ | |||
138690 138691 138692 138693 138694 138695 138696 138697 138698 138699 138700 138701 138702 138703 |
** 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 );
|
| ︙ | ︙ | |||
138980 138981 138982 138983 138984 138985 138986 |
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
|
| ︙ | ︙ | |||
139810 139811 139812 139813 139814 139815 139816 |
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;
}
}
|
| ︙ | ︙ | |||
140550 140551 140552 140553 140554 140555 140556 140557 140558 140559 140560 140561 140562 140563 |
#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]);
|
| ︙ | ︙ | |||
140579 140580 140581 140582 140583 140584 140585 |
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,
|
| ︙ | ︙ | |||
143605 143606 143607 143608 143609 143610 143611 143612 143613 143614 143615 143616 143617 143618 |
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);
|
| ︙ | ︙ | |||
144021 144022 144023 144024 144025 144026 144027 |
*/
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 */
};
/*
|
| ︙ | ︙ | |||
144331 144332 144333 144334 144335 144336 144337 144338 144339 144340 144341 144342 144343 144344 | #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 |
| ︙ | ︙ | |||
144614 144615 144616 144617 144618 144619 144620 144621 144622 144623 144624 144625 144626 144627 |
&& (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++;
}
|
| ︙ | ︙ | |||
144931 144932 144933 144934 144935 144936 144937 |
}
}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.
**
|
| ︙ | ︙ | |||
145017 145018 145019 145020 145021 145022 145023 145024 145025 145026 145027 145028 145029 145030 |
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);
|
| ︙ | ︙ | |||
145051 145052 145053 145054 145055 145056 145057 |
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;
}
}
|
| ︙ | ︙ | |||
145417 145418 145419 145420 145421 145422 145423 |
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.
|
| ︙ | ︙ | |||
146044 146045 146046 146047 146048 146049 146050 |
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
|
| ︙ | ︙ | |||
146467 146468 146469 146470 146471 146472 146473 |
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"));
|
| ︙ | ︙ | |||
146601 146602 146603 146604 146605 146606 146607 146608 146609 146610 146611 146612 146613 146614 |
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;
|
| ︙ | ︙ | |||
147318 147319 147320 147321 147322 147323 147324 147325 147326 147327 147328 147329 147330 147331 |
){
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;
|
| ︙ | ︙ | |||
147678 147679 147680 147681 147682 147683 147684 |
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);
}
}
}
}
|
| ︙ | ︙ | |||
147802 147803 147804 147805 147806 147807 147808 147809 147810 147811 147812 147813 147814 147815 147816 147817 147818 147819 147820 |
** 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.
**
|
| ︙ | ︙ | |||
148183 148184 148185 148186 148187 148188 148189 148190 148191 148192 148193 148194 148195 148196 |
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;
|
| ︙ | ︙ | |||
148275 148276 148277 148278 148279 148280 148281 |
*/
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 ){
|
| ︙ | ︙ | |||
148971 148972 148973 148974 148975 148976 148977 |
/*
** 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.
|
| ︙ | ︙ | |||
149046 149047 149048 149049 149050 149051 149052 149053 149054 149055 149056 149057 149058 149059 |
&& 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 );
|
| ︙ | ︙ | |||
150650 150651 150652 150653 150654 150655 150656 |
/*
** 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 ){
|
| ︙ | ︙ | |||
150692 150693 150694 150695 150696 150697 150698 150699 150700 150701 150702 150703 150704 150705 |
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
|
| ︙ | ︙ | |||
151198 151199 151200 151201 151202 151203 151204 151205 151206 151207 151208 151209 151210 151211 |
}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;
|
| ︙ | ︙ | |||
151280 151281 151282 151283 151284 151285 151286 |
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.
**
|
| ︙ | ︙ | |||
151303 151304 151305 151306 151307 151308 151309 |
** 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(
|
| ︙ | ︙ | |||
151474 151475 151476 151477 151478 151479 151480 151481 151482 151483 151484 151485 151486 151487 |
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
|
| ︙ | ︙ | |||
151595 151596 151597 151598 151599 151600 151601 151602 151603 151604 151605 151606 151607 151608 |
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;
}
|
| ︙ | ︙ | |||
152305 152306 152307 152308 152309 152310 152311 |
#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;
|
| ︙ | ︙ | |||
152574 152575 152576 152577 152578 152579 152580 152581 152582 152583 152584 152585 152586 152587 |
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.
*/
|
| ︙ | ︙ | |||
152641 152642 152643 152644 152645 152646 152647 |
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 |
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++){
|
| ︙ | ︙ | |||
152832 152833 152834 152835 152836 152837 152838 |
** 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
|
| ︙ | ︙ | |||
154024 154025 154026 154027 154028 154029 154030 154031 154032 154033 154034 154035 154036 154037 |
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;
}
/*
|
| ︙ | ︙ | |||
154120 154121 154122 154123 154124 154125 154126 154127 154128 154129 154130 154131 154132 154133 |
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 ){
|
| ︙ | ︙ | |||
154144 154145 154146 154147 154148 154149 154150 154151 154152 154153 154154 154155 154156 154157 |
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);
}
|
| ︙ | ︙ | |||
154323 154324 154325 154326 154327 154328 154329 |
}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 ******************************************/
|
| ︙ | ︙ | |||
155282 155283 155284 155285 155286 155287 155288 155289 155290 155291 155292 155293 155294 155295 155296 155297 155298 |
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;
|
| ︙ | ︙ | |||
155316 155317 155318 155319 155320 155321 155322 155323 155324 155325 155326 155327 155328 155329 |
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;
|
| ︙ | ︙ | |||
155912 155913 155914 155915 155916 155917 155918 155919 155920 155921 155922 155923 155924 155925 | 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; }; /* |
| ︙ | ︙ | |||
156588 156589 156590 156591 156592 156593 156594 |
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:
|
| ︙ | ︙ | |||
157094 157095 157096 157097 157098 157099 157100 | 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 */ |
| ︙ | ︙ | |||
157166 157167 157168 157169 157170 157171 157172 | /* 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;
}
|
| ︙ | ︙ | |||
157222 157223 157224 157225 157226 157227 157228 |
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);
|
| ︙ | ︙ | |||
157342 157343 157344 157345 157346 157347 157348 157349 157350 157351 157352 157353 157354 157355 |
/* 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);
|
| ︙ | ︙ | |||
157815 157816 157817 157818 157819 157820 157821 | #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. |
| ︙ | ︙ | |||
157876 157877 157878 157879 157880 157881 157882 | ** 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
|
| ︙ | ︙ | |||
157992 157993 157994 157995 157996 157997 157998 | ** 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,
|
| ︙ | ︙ | |||
158786 158787 158788 158789 158790 158791 158792 158793 158794 158795 158796 158797 158798 158799 |
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:
|
| ︙ | ︙ | |||
159057 159058 159059 159060 159061 159062 159063 | /* 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[] = {
|
| ︙ | ︙ | |||
159722 159723 159724 159725 159726 159727 159728 |
** 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 */
}
}
|
| ︙ | ︙ | |||
160105 160106 160107 160108 160109 160110 160111 |
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 */
|
| ︙ | ︙ | |||
160957 160958 160959 160960 160961 160962 160963 |
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 */
{
|
| ︙ | ︙ | |||
160989 160990 160991 160992 160993 160994 160995 |
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;
|
| ︙ | ︙ | |||
161058 161059 161060 161061 161062 161063 161064 |
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;
|
| ︙ | ︙ | |||
161978 161979 161980 161981 161982 161983 161984 |
{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 "
|
| ︙ | ︙ | |||
162047 162048 162049 162050 162051 162052 162053 |
{
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);
|
| ︙ | ︙ | |||
162793 162794 162795 162796 162797 162798 162799 162800 162801 162802 162803 162804 162805 162806 162807 162808 162809 162810 162811 |
#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,
|
| ︙ | ︙ | |||
163755 163756 163757 163758 163759 163760 163761 163762 163763 163764 163765 163766 163767 163768 |
#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;
}
|
| ︙ | ︙ | |||
164774 164775 164776 164777 164778 164779 164780 |
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);
|
| ︙ | ︙ | |||
165189 165190 165191 165192 165193 165194 165195 |
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);
|
| ︙ | ︙ | |||
165743 165744 165745 165746 165747 165748 165749 | 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); }
|
| ︙ | ︙ | |||
166353 166354 166355 166356 166357 166358 166359 166360 166361 166362 166363 166364 166365 166366 |
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;
}
|
| ︙ | ︙ | |||
168748 168749 168750 168751 168752 168753 168754 168755 168756 168757 168758 168759 168760 168761 |
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;
}
/*
|
| ︙ | ︙ | |||
172319 172320 172321 172322 172323 172324 172325 |
){
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 */
|
| ︙ | ︙ | |||
172389 172390 172391 172392 172393 172394 172395 |
** 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;
}
|
| ︙ | ︙ | |||
175550 175551 175552 175553 175554 175555 175556 |
/* 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);
|
| ︙ | ︙ | |||
176935 176936 176937 176938 176939 176940 176941 176942 176943 176944 176945 176946 176947 176948 |
}
/* 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]);
|
| ︙ | ︙ | |||
182456 182457 182458 182459 182460 182461 182462 |
}
}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:
|
| ︙ | ︙ | |||
182652 182653 182654 182655 182656 182657 182658 |
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.
*/
|
| ︙ | ︙ | |||
183652 183653 183654 183655 183656 183657 183658 |
}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);
|
| ︙ | ︙ | |||
186466 186467 186468 186469 186470 186471 186472 186473 186474 186475 186476 186477 186478 186479 | /* #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 */ |
| ︙ | ︙ | |||
186516 186517 186518 186519 186520 186521 186522 |
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 */
|
| ︙ | ︙ | |||
186683 186684 186685 186686 186687 186688 186689 | ** 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).
|
| ︙ | ︙ | |||
186792 186793 186794 186795 186796 186797 186798 | } /* ** 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;
}
|
| ︙ | ︙ | |||
186878 186879 186880 186881 186882 186883 186884 |
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 );
|
| ︙ | ︙ | |||
186924 186925 186926 186927 186928 186929 186930 |
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;
|
| ︙ | ︙ | |||
187988 187989 187990 187991 187992 187993 187994 |
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);
|
| ︙ | ︙ | |||
189285 189286 189287 189288 189289 189290 189291 |
/* 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++] = '\\';
|
| ︙ | ︙ | |||
190884 190885 190886 190887 190888 190889 190890 |
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 ){
|
| ︙ | ︙ | |||
190945 190946 190947 190948 190949 190950 190951 | 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
/*
|
| ︙ | ︙ | |||
190988 190989 190990 190991 190992 190993 190994 |
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]);
}
}
|
| ︙ | ︙ | |||
195510 195511 195512 195513 195514 195515 195516 195517 195518 195519 195520 |
** 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().
*/
|
| ︙ | ︙ | |||
201037 201038 201039 201040 201041 201042 201043 |
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 = ", ";
}
|
| ︙ | ︙ | |||
204409 204410 204411 204412 204413 204414 204415 |
** 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;
|
| ︙ | ︙ | |||
206043 206044 206045 206046 206047 206048 206049 206050 206051 206052 206053 206054 206055 206056 206057 206058 206059 206060 206061 206062 206063 |
/*
** 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 */
};
/*
|
| ︙ | ︙ | |||
206292 206293 206294 206295 206296 206297 206298 |
*/
/*
** 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
|
| ︙ | ︙ | |||
207122 207123 207124 207125 207126 207127 207128 207129 207130 207131 207132 207133 207134 207135 |
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
|
| ︙ | ︙ | |||
207167 207168 207169 207170 207171 207172 207173 207174 207175 207176 207177 207178 207179 207180 |
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
|
| ︙ | ︙ | |||
207240 207241 207242 207243 207244 207245 207246 |
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 */
|
| ︙ | ︙ | |||
207266 207267 207268 207269 207270 207271 207272 |
/* 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 ){
|
| ︙ | ︙ | |||
207864 207865 207866 207867 207868 207869 207870 | /* ** 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;
|
| ︙ | ︙ | |||
208521 208522 208523 208524 208525 208526 208527 |
** 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,
|
| ︙ | ︙ | |||
208612 208613 208614 208615 208616 208617 208618 208619 208620 208621 208622 208623 208624 208625 |
/*
** 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),
|
| ︙ | ︙ | |||
215433 215434 215435 215436 215437 215438 215439 215440 215441 215442 215443 215444 215445 215446 215447 215448 215449 215450 215451 215452 |
/* 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
|
| ︙ | ︙ | |||
215487 215488 215489 215490 215491 215492 215493 |
** 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
){
|
| ︙ | ︙ | |||
216196 216197 216198 216199 216200 216201 216202 | 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 |
| ︙ | ︙ | |||
219032 219033 219034 219035 219036 219037 219038 219039 219040 219041 219042 219043 219044 219045 |
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){
|
| ︙ | ︙ | |||
219398 219399 219400 219401 219402 219403 219404 219405 219406 219407 219408 219409 219410 219411 219412 219413 219414 219415 219416 219417 219418 219419 219420 219421 219422 219423 219424 219425 219426 219427 219428 219429 219430 219431 219432 219433 219434 |
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;
|
| ︙ | ︙ | |||
220667 220668 220669 220670 220671 220672 220673 |
*/
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;
|
| ︙ | ︙ | |||
221847 221848 221849 221850 221851 221852 221853 |
}
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;
|
| ︙ | ︙ | |||
221880 221881 221882 221883 221884 221885 221886 |
**
** 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;
}
|
| ︙ | ︙ | |||
222308 222309 222310 222311 222312 222313 222314 |
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 );
}
}
|
| ︙ | ︙ | |||
223420 223421 223422 223423 223424 223425 223426 |
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 ){
|
| ︙ | ︙ | |||
224777 224778 224779 224780 224781 224782 224783 |
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);
|
| ︙ | ︙ | |||
225216 225217 225218 225219 225220 225221 225222 |
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};
|
| ︙ | ︙ | |||
225315 225316 225317 225318 225319 225320 225321 |
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 ){
|
| ︙ | ︙ | |||
226956 226957 226958 226959 226960 226961 226962 226963 226964 226965 226966 226967 226968 226969 |
rc = sqlite3_create_function(
db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
);
}
return rc;
#else
return SQLITE_OK;
#endif
}
static int sqlite3Fts5IndexReset(Fts5Index *p){
assert( p->pStruct==0 || p->iStructVersion!=0 );
if( fts5IndexDataVersion(p)!=p->iStructVersion ){
| > | 227759 227760 227761 227762 227763 227764 227765 227766 227767 227768 227769 227770 227771 227772 227773 |
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 ){
|
| ︙ | ︙ | |||
228919 228920 228921 228922 228923 228924 228925 |
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;
|
| ︙ | ︙ | |||
229760 229761 229762 229763 229764 229765 229766 |
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){
|
| ︙ | ︙ | |||
234686 234687 234688 234689 234690 234691 234692 | #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.
| ︙ | ︙ | |||
121 122 123 124 125 126 127 | ** ** 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 | | | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | ** ** 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 |
| ︙ | ︙ | |||
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 | ** 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> */ #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 | > > > > | 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 | ** 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 |
| ︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 | #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 | < > | 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 |
| ︙ | ︙ | |||
4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 | ** 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 ** |
| ︙ | ︙ | |||
4359 4360 4361 4362 4363 4364 4365 | ** 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 |
| ︙ | ︙ | |||
5112 5113 5114 5115 5116 5117 5118 | ** 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 |
| ︙ | ︙ | |||
7790 7791 7792 7793 7794 7795 7796 | #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, |
| ︙ | ︙ | |||
9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 |
**
** ^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
|
| ︙ | ︙ | |||
9800 9801 9802 9803 9804 9805 9806 | ** 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 */ ); |
| ︙ | ︙ | |||
9852 9853 9854 9855 9856 9857 9858 | ** 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[] */ |
| ︙ | ︙ | |||
10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 | ** ** 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 |
| ︙ | ︙ | |||
10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 | */ 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.
| ︙ | ︙ | |||
903 904 905 906 907 908 909 910 911 912 913 914 915 916 |
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.
| ︙ | ︙ | |||
766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
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.
*/
| > > > | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
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.
*/
|
| ︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 |
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(",");
| > > | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 |
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(",");
|
| ︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 |
"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>");
| | | 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 |
"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,
|
| ︙ | ︙ | |||
1527 1528 1529 1530 1531 1532 1533 |
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>:
| | | 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 |
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();
|
| ︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 | @ count(*) AS wcnt @ FROM @ tag, @ tagxref @ WHERE @ tag.tagname GLOB 'wiki-*' @ AND tagxref.tagid=tag.tagid @ GROUP BY 1 @ ORDER BY 2; ; /* ** WEBPAGE: wcontent ** | > | 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 | @ 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/changes.wiki.
1 2 3 4 5 6 7 8 9 10 11 12 |
<title>Change Log</title>
<a name='v2_16'></a>
<h2>Changes for Version 2.16 (pending)</h2>
* [/wcontent|Listing] of the available wiki pages
[/timeline?r=wcontent-subsets|gained] the ability to
[./javascript.md#wcontent|interactively] adjust a subset of
wiki pages that are shown; this is based on the
classification of wiki page names according to the
[/help?cmd=wiki-classes|configurable] glob patterns.
<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 46 47 48 49 50 51 |
<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.
* [/wcontent|Listing] of the available wiki pages
[/timeline?r=wcontent-subsets|gained] the ability to
[./javascript.md#wcontent|interactively] adjust a subset of
wiki pages that are shown; this is based on the
classification of wiki page names according to the
[/help?cmd=wiki-classes|configurable] glob patterns.
<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.
|
| ︙ | ︙ | |||
87 88 89 90 91 92 93 |
* 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>
| | > > > > | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
* 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="wcontent"></a>Wiki content listing
[Since](/timeline?r=wcontent-subsets) version 2.16 it is possible to
add [configurable](/help?cmd=wiki-classes) checkbox controls to the
submenu of [available wiki pages](/wcontent) for the interactive
adjustment of a subset of wiki pages that are shown.
Client-side script is used to toggle visibility of the corresponding
| > > > > > > > > > > > > > | 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="wcontent"></a>Wiki content listing
[Since](/timeline?r=wcontent-subsets) version 2.16 it is possible to
add [configurable](/help?cmd=wiki-classes) checkbox controls to the
submenu of [available wiki pages](/wcontent) for the interactive
adjustment of a subset of wiki pages that are shown.
Client-side script is used to toggle visibility of the corresponding
|
| ︙ | ︙ | |||
613 614 615 616 617 618 619 | 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 | | | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | 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/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.
|
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
|