SQLite

Changes On Branch bad-merge
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch bad-merge Excluding Merge-Ins

This is equivalent to a diff from e69f29892e to c5e2de1d24

2021-05-22
15:05
Merge latest trunk changes into this branch. (check-in: dbc65a6958 user: dan tags: reuse-schema)
2021-05-07
14:16
This was suppose to be a merge from trunk. But something went wrong. (Closed-Leaf check-in: c5e2de1d24 user: dan tags: bad-merge)
2021-04-07
15:23
Merge version 3.35.4 with this branch. (check-in: 4b4f87913a user: dan tags: reuse-schema-3.35)
15:13
Update a broken assert() on this branch. (check-in: e69f29892e user: dan tags: reuse-schema)
2021-03-26
13:16
Merge in changes for 3.35.3 (check-in: 76f19f4bcf user: drh tags: reuse-schema)

Changes to Makefile.in.
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443







-
+







  $(TOP)/src/test_vfs.c \
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_window.c \
  $(TOP)/src/test_wsd.c       \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_test.c  \
  $(TOP)/ext/session/test_session.c \
  $(TOP)/ext/rbu/test_rbu.c
  $(TOP)/ext/rbu/test_rbu.c 

# Statically linked extensions
#
TESTSRC += \
  $(TOP)/ext/expert/sqlite3expert.c \
  $(TOP)/ext/expert/test_expert.c \
  $(TOP)/ext/misc/amatch.c \
519
520
521
522
523
524
525
526


527
528
529
530
531
532
533
519
520
521
522
523
524
525

526
527
528
529
530
531
532
533
534







-
+
+







  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/misc/stmt.c
  $(TOP)/ext/misc/stmt.c \
  fts5.c

# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \
Changes to Makefile.msc.
1549
1550
1551
1552
1553
1554
1555
1556

1557
1558
1559
1560
1561
1562
1563
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563







-
+







  $(TOP)\src\test_vfs.c \
  $(TOP)\src\test_windirent.c \
  $(TOP)\src\test_window.c \
  $(TOP)\src\test_wsd.c \
  $(TOP)\ext\fts3\fts3_term.c \
  $(TOP)\ext\fts3\fts3_test.c \
  $(TOP)\ext\rbu\test_rbu.c \
  $(TOP)\ext\session\test_session.c
  $(TOP)\ext\session\test_session.c 

# Statically linked extensions.
#
TESTEXT = \
  $(TOP)\ext\expert\sqlite3expert.c \
  $(TOP)\ext\expert\test_expert.c \
  $(TOP)\ext\misc\amatch.c \
1582
1583
1584
1585
1586
1587
1588
1589


1590
1591
1592
1593
1594
1595
1596
1582
1583
1584
1585
1586
1587
1588

1589
1590
1591
1592
1593
1594
1595
1596
1597







-
+
+







  $(TOP)\ext\misc\prefixes.c \
  $(TOP)\ext\misc\regexp.c \
  $(TOP)\ext\misc\remember.c \
  $(TOP)\ext\misc\series.c \
  $(TOP)\ext\misc\spellfix.c \
  $(TOP)\ext\misc\totype.c \
  $(TOP)\ext\misc\unionvtab.c \
  $(TOP)\ext\misc\wholenumber.c
  $(TOP)\ext\misc\wholenumber.c \
  fts5.c

# If use of zlib is enabled, add the "zipfile.c" source file.
#
!IF $(USE_ZLIB)!=0
TESTEXT = $(TESTEXT) $(TOP)\ext\misc\zipfile.c
!ENDIF

Changes to README.md.
51
52
53
54
55
56
57
58

59
60
61
62



63
64
65
66
67
68
69
51
52
53
54
55
56
57

58
59



60
61
62
63
64
65
66
67
68
69







-
+

-
-
-
+
+
+







first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html).  Fossil is
a stand-alone program.  To install, simply download or build the single 
executable file and put that file someplace on your $PATH.)
Then run commands like this:

        mkdir ~/sqlite
        mkdir -p ~/sqlite ~/Fossils
        cd ~/sqlite
        fossil clone https://www.sqlite.org/src sqlite.fossil
        fossil open sqlite.fossil
    
        fossil clone https://www.sqlite.org/src ~/Fossils/sqlite.fossil
        fossil open ~/Fossils/sqlite.fossil

After setting up a repository using the steps above, you can always
update to the lastest version using:

        fossil update trunk   ;# latest trunk check-in
        fossil update release ;# latest official release

Or type "fossil ui" to get a web-based user interface.
Changes to VERSION.
1


1
-
+
3.35.3
3.36.0
Changes to configure.
1
2
3

4
5
6
7
8
9
10
1
2

3
4
5
6
7
8
9
10


-
+







#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.35.3.
# Generated by GNU Autoconf 2.69 for sqlite 3.36.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
722
723
724
725
726
727
728
729
730


731
732
733
734
735
736
737
722
723
724
725
726
727
728


729
730
731
732
733
734
735
736
737







-
-
+
+







subdirs=
MFLAGS=
MAKEFLAGS=

# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.35.3'
PACKAGE_STRING='sqlite 3.35.3'
PACKAGE_VERSION='3.36.0'
PACKAGE_STRING='sqlite 3.36.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
1463
1464
1465
1466
1467
1468
1469
1470

1471
1472
1473
1474
1475
1476
1477
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472
1473
1474
1475
1476
1477







-
+







#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures sqlite 3.35.3 to adapt to many kinds of systems.
\`configure' configures sqlite 3.36.0 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537
1538
1539
1540
1541
1542
1528
1529
1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1542







-
+







  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi

if test -n "$ac_init_help"; then
  case $ac_init_help in
     short | recursive ) echo "Configuration of sqlite 3.35.3:";;
     short | recursive ) echo "Configuration of sqlite 3.36.0:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
1656
1657
1658
1659
1660
1661
1662
1663

1664
1665
1666
1667
1668
1669
1670
1656
1657
1658
1659
1660
1661
1662

1663
1664
1665
1666
1667
1668
1669
1670







-
+







    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
sqlite configure 3.35.3
sqlite configure 3.36.0
generated by GNU Autoconf 2.69

Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
2075
2076
2077
2078
2079
2080
2081
2082

2083
2084
2085
2086
2087
2088
2089
2075
2076
2077
2078
2079
2080
2081

2082
2083
2084
2085
2086
2087
2088
2089







-
+







  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

} # ac_fn_c_check_header_mongrel
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by sqlite $as_me 3.35.3, which was
It was created by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69.  Invocation command line was

  $ $0 $@

_ACEOF
exec 5>>config.log
{
12374
12375
12376
12377
12378
12379
12380
12381

12382
12383
12384
12385
12386
12387
12388
12374
12375
12376
12377
12378
12379
12380

12381
12382
12383
12384
12385
12386
12387
12388







-
+







test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.35.3, which was
This file was extended by sqlite $as_me 3.36.0, which was
generated by GNU Autoconf 2.69.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@
12440
12441
12442
12443
12444
12445
12446
12447

12448
12449
12450
12451
12452
12453
12454
12440
12441
12442
12443
12444
12445
12446

12447
12448
12449
12450
12451
12452
12453
12454







-
+








Report bugs to the package provider."

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.35.3
sqlite config.status 3.36.0
configured by $0, generated by GNU Autoconf 2.69,
  with options \\"\$ac_cs_config\\"

Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."

Changes to doc/lemon.html.
693
694
695
696
697
698
699

700
701
702
703
704
705
706
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707







+







<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
<li><tt><a href='#pright'>%right</a></tt>
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
<li><tt><a href='#stack_size'>%stack_size</a></tt>
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
<li><tt><a href='#token'>%token</a></tt>
<li><tt><a href='#token_class'>%token_class</a></tt>
<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
<li><tt><a href='#token_type'>%token_type</a></tt>
<li><tt><a href='#ptype'>%type</a></tt>
<li><tt><a href='#pwildcard'>%wildcard</a></tt>
</ul>
1074
1075
1076
1077
1078
1079
1080
1081























1082
1083

1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105

1106
1107
1108
1109
1110
1111
1112
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
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
1130
1131
1132
1133
1134
1135
1136








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+





-
+















-
+







   %start_symbol  prog
</pre>

<a id='syntax_error'></a>
<h4>4.4.19 The <tt>%syntax_error</tt> directive</h4>

<p>See <a href='#errors'>Error Processing</a>.</p>

<a id='token'></a>
<h4>4.4.20 The <tt>%token</tt> directive</h4>

<p>Tokens are normally created automatically, the first time they are used.
Any identifier that begins with an upper-case letter is a token.

<p>Sometimes it is useful to declare tokens in advance, however.  The
integer values assigned to each token determined by the order in which
the tokens are seen.  So by declaring tokens in advance, it is possible to
cause some tokens to have low-numbered values, which might be desirable in
some grammers, or to have sequential values assigned to a sequence of
related tokens.  For this reason, the %token directive is provided to
declare tokens in advance.  The syntax is as follows:

<blockquote>
<tt>%token</tt> <i>TOKEN</i> <i>TOKEN...</i> <b>.</b>
</blockquote></p>

<p>The %token directive is followed by zero or more token symbols and
terminated by a single ".".  Each token named is created if it does not
already exist.  Tokens are created in order.


<a id='token_class'></a>
<h4>4.4.20 The <tt>%token_class</tt> directive</h4>
<h4>4.4.21 The <tt>%token_class</tt> directive</h4>

<p>Undocumented.  Appears to be related to the MULTITERMINAL concept.
<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>

<a id='token_destructor'></a>
<h4>4.4.21 The <tt>%token_destructor</tt> directive</h4>
<h4>4.4.22 The <tt>%token_destructor</tt> directive</h4>

<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
symbol.  (See the description of the
<tt><a href='%destructor'>%destructor</a></tt> directive above.)
The <tt>%token_destructor</tt> directive does the same thing
for all terminal symbols.</p>

<p>Unlike non-terminal symbols, which may each have a different data type
for their values, terminals all use the same data type (defined by
the <tt><a href='#token_type'>%token_type</a></tt> directive)
and so they use a common destructor.
Other than that, the token destructor works just like the non-terminal
destructors.</p>

<a id='token_prefix'></a>
<h4>4.4.22 The <tt>%token_prefix</tt> directive</h4>
<h4>4.4.23 The <tt>%token_prefix</tt> directive</h4>

<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar.  If desired, Lemon will
add a prefix specified by this directive
to each of the #defines it generates.</p>

<p>So if the default output of Lemon looked like this:</p>
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
1163







-
+







    #define TOKEN_AND        1
    #define TOKEN_MINUS      2
    #define TOKEN_OR         3
    #define TOKEN_PLUS       4
</pre>

<a id='token_type'></a><a id='ptype'></a>
<h4>4.4.23 The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
<h4>4.4.24 The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>

<p>These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
symbols.  The values of all terminal symbols must be of the same
type.  This turns out to be the same data type as the 3rd parameter
to the Parse() function generated by Lemon.  Typically, you will
make the value of a terminal symbol be a pointer to some kind of
1162
1163
1164
1165
1166
1167
1168
1169

1170
1171
1172
1173
1174
1175
1176
1186
1187
1188
1189
1190
1191
1192

1193
1194
1195
1196
1197
1198
1199
1200







-
+







the grammar designer should keep in mind that the size of the union
will be the size of its largest element.  So if you have a single
non-terminal whose data type requires 1K of storage, then your 100
entry parser stack will require 100K of heap space.  If you are willing
and able to pay that price, fine.  You just need to know.</p>

<a id='pwildcard'></a>
<h4>4.4.24 The <tt>%wildcard</tt> directive</h4>
<h4>4.4.25 The <tt>%wildcard</tt> directive</h4>

<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
period.  This directive specifies that the identified token should
match any input token.</p>

<p>When the generated parser has the choice of matching an input against
the wildcard token and some other token, the other token is always used.
Changes to ext/expert/expert1.test.
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
239
240
241
242
243


244
245
246
247
248
249
250
251
252
253
254
255
256
257

258
259

260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318


319
320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360

361
362
363
364
365
366
367
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
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

257
258

259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316


317
318
319
320
321
322
323
324
325
326

327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351

352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367

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







-
+








-
+








-
+








-
+








-
+









-
+









-
+








-
+








-
+







-
+











-
+








-
+










-
+








-
+












-
-
+
+













-
+

-
+










-
+







-
+







-
+














-
+















-
-
+
+








-
+








-
+







-
+







-
+







-
+







-
+











-
+










-
+







  eval $setup


do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
  SELECT * FROM t1
} {
  (no new indexes)
  SCAN TABLE t1
  SCAN t1
}

do_setup_rec_test $tn.2 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT * FROM t1 WHERE b>?;
} {
  CREATE INDEX t1_idx_00000062 ON t1(b);
  SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
  SEARCH t1 USING INDEX t1_idx_00000062 (b>?)
}

do_setup_rec_test $tn.3 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
} {
  CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
  SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
  SEARCH t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
}

do_setup_rec_test $tn.4 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT a FROM t1 ORDER BY b;
} {
  CREATE INDEX t1_idx_00000062 ON t1(b);
  SCAN TABLE t1 USING INDEX t1_idx_00000062
  SCAN t1 USING INDEX t1_idx_00000062
}

do_setup_rec_test $tn.5 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT a FROM t1 WHERE a=? ORDER BY b;
} {
  CREATE INDEX t1_idx_000123a7 ON t1(a, b);
  SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
  SEARCH t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
}

if 0 {
do_setup_rec_test $tn.6 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT min(a) FROM t1
} {
  CREATE INDEX t1_idx_00000061 ON t1(a);
  SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
  SEARCH t1 USING COVERING INDEX t1_idx_00000061
}
}

do_setup_rec_test $tn.7 {
  CREATE TABLE t1(a, b, c);
} {
  SELECT * FROM t1 ORDER BY a, b, c;
} {
  CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
  SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
  SCAN t1 USING COVERING INDEX t1_idx_033e95fe
}

#do_setup_rec_test $tn.1.8 {
#  CREATE TABLE t1(a, b, c);
#} {
#  SELECT * FROM t1 ORDER BY a ASC, b COLLATE nocase DESC, c ASC;
#} {
#  CREATE INDEX t1_idx_5be6e222 ON t1(a, b COLLATE NOCASE DESC, c);
#  0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5be6e222
#  0|0|0|SCAN t1 USING COVERING INDEX t1_idx_5be6e222
#}

do_setup_rec_test $tn.8.1 {
  CREATE TABLE t1(a COLLATE NOCase, b, c);
} {
  SELECT * FROM t1 WHERE a=?
} {
  CREATE INDEX t1_idx_00000061 ON t1(a);
  SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
  SEARCH t1 USING INDEX t1_idx_00000061 (a=?)
}
do_setup_rec_test $tn.8.2 {
  CREATE TABLE t1(a, b COLLATE nocase, c);
} {
  SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
} {
  CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
  SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
  SCAN t1 USING COVERING INDEX t1_idx_5cb97285
}


# Tables with names that require quotes.
#
do_setup_rec_test $tn.9.1 {
  CREATE TABLE "t t"(a, b, c);
} {
  SELECT * FROM "t t" WHERE a=?
} {
  CREATE INDEX 't t_idx_00000061' ON 't t'(a);
  SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?) 
  SEARCH t t USING INDEX t t_idx_00000061 (a=?) 
}

do_setup_rec_test $tn.9.2 {
  CREATE TABLE "t t"(a, b, c);
} {
  SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
} {
  CREATE INDEX 't t_idx_00000062' ON 't t'(b);
  SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
  SEARCH t t USING INDEX t t_idx_00000062 (b>? AND b<?)
}

# Columns with names that require quotes.
#
do_setup_rec_test $tn.10.1 {
  CREATE TABLE t3(a, "b b", c);
} {
  SELECT * FROM t3 WHERE "b b" = ?
} {
  CREATE INDEX t3_idx_00050c52 ON t3('b b');
  SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
  SEARCH t3 USING INDEX t3_idx_00050c52 (b b=?)
}

do_setup_rec_test $tn.10.2 {
  CREATE TABLE t3(a, "b b", c);
} {
  SELECT * FROM t3 ORDER BY "b b"
} {
  CREATE INDEX t3_idx_00050c52 ON t3('b b');
  SCAN TABLE t3 USING INDEX t3_idx_00050c52
  SCAN t3 USING INDEX t3_idx_00050c52
}

# Transitive constraints
#
do_setup_rec_test $tn.11.1 {
  CREATE TABLE t5(a, b);
  CREATE TABLE t6(c, d);
} {
  SELECT * FROM t5, t6 WHERE a=? AND b=c AND c=?
} {
  CREATE INDEX t5_idx_000123a7 ON t5(a, b);
  CREATE INDEX t6_idx_00000063 ON t6(c);
  SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?) 
  SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
  SEARCH t6 USING INDEX t6_idx_00000063 (c=?) 
  SEARCH t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
}

# OR terms.
#
do_setup_rec_test $tn.12.1 {
  CREATE TABLE t7(a, b);
} {
  SELECT * FROM t7 WHERE a=? OR b=?
} {
  CREATE INDEX t7_idx_00000062 ON t7(b);
  CREATE INDEX t7_idx_00000061 ON t7(a);
  MULTI-INDEX OR
    INDEX 1
      SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) 
      SEARCH t7 USING INDEX t7_idx_00000061 (a=?) 
    INDEX 2
      SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
      SEARCH t7 USING INDEX t7_idx_00000062 (b=?)
}

# rowid terms.
#
do_setup_rec_test $tn.13.1 {
  CREATE TABLE t8(a, b);
} {
  SELECT * FROM t8 WHERE rowid=?
} {
  (no new indexes)
  SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
  SEARCH t8 USING INTEGER PRIMARY KEY (rowid=?)
}
do_setup_rec_test $tn.13.2 {
  CREATE TABLE t8(a, b);
} {
  SELECT * FROM t8 ORDER BY rowid
} {
  (no new indexes)
  SCAN TABLE t8
  SCAN t8
}
do_setup_rec_test $tn.13.3 {
  CREATE TABLE t8(a, b);
} {
  SELECT * FROM t8 WHERE a=? ORDER BY rowid
} {
  CREATE INDEX t8_idx_00000061 ON t8(a); 
  SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
  SEARCH t8 USING INDEX t8_idx_00000061 (a=?)
}

# Triggers
#
do_setup_rec_test $tn.14 {
  CREATE TABLE t9(a, b, c);
  CREATE TABLE t10(a, b, c);
  CREATE TRIGGER t9t AFTER INSERT ON t9 BEGIN
    UPDATE t10 SET a=new.a WHERE b = new.b;
  END;
} {
  INSERT INTO t9 VALUES(?, ?, ?);
} {
  CREATE INDEX t10_idx_00000062 ON t10(b); 
  SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
  SEARCH t10 USING INDEX t10_idx_00000062 (b=?)
}

do_setup_rec_test $tn.15 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);

  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
  INSERT INTO t1 SELECT (i-1)/50, (i-1)/20 FROM s;

  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100)
  INSERT INTO t2 SELECT (i-1)/20, (i-1)/5 FROM s;
} {
  SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
} {
  CREATE INDEX t2_idx_00000064 ON t2(d);
  SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?) 
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
  SEARCH t2 USING INDEX t2_idx_00000064 (d=?) 
  SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}

do_setup_rec_test $tn.16 {
  CREATE TABLE t1(a, b);
} {
  SELECT * FROM t1 WHERE b IS NOT NULL;
} {
  (no new indexes)
  SCAN TABLE t1
  SCAN t1
}

do_setup_rec_test $tn.17.1 {
  CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
} {
  SELECT * FROM example WHERE a=?
} {
  (no new indexes)
  SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=?)
  SEARCH example USING INDEX sqlite_autoindex_example_1 (A=?)
}
do_setup_rec_test $tn.17.2 {
  CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
} {
  SELECT * FROM example WHERE b=?
} {
  CREATE INDEX example_idx_00000042 ON example(B);
  SEARCH TABLE example USING INDEX example_idx_00000042 (B=?)
  SEARCH example USING INDEX example_idx_00000042 (B=?)
}
do_setup_rec_test $tn.17.3 {
  CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
} {
  SELECT * FROM example WHERE a=? AND b=?
} {
  (no new indexes)
  SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
  SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
}
do_setup_rec_test $tn.17.4 {
  CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
} {
  SELECT * FROM example WHERE a=? AND b>?
} {
  (no new indexes)
  SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
  SEARCH example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
}
do_setup_rec_test $tn.17.5 {
  CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
} {
  SELECT * FROM example WHERE a>? AND b=?
} {
  CREATE INDEX example_idx_0000cb3f ON example(B, A);
  SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
  SEARCH example USING INDEX example_idx_0000cb3f (B=? AND A>?)
}

do_setup_rec_test $tn.18.0 {
  CREATE TABLE SomeObject (
     a INTEGER PRIMARY KEY,
     x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
  );
} {
  SELECT x FROM SomeObject;
} {
  (no new indexes)
  SCAN TABLE SomeObject
  SCAN SomeObject
}
do_setup_rec_test $tn.18.1 {
  CREATE TABLE SomeObject (
     a INTEGER PRIMARY KEY,
     x TEXT GENERATED ALWAYS AS(HEX(a)) VIRTUAL
  );
} {
  SELECT * FROM SomeObject WHERE x=?;
} {
  CREATE INDEX SomeObject_idx_00000078 ON SomeObject(x);
  SEARCH TABLE SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
  SEARCH SomeObject USING COVERING INDEX SomeObject_idx_00000078 (x=?)
}

}

proc do_candidates_test {tn sql res} {
  set res [squish [string trim $res]]

451
452
453
454
455
456
457
458
451
452
453
454
455
456
457








-
  t1 t1_idx_000123a7 {100 50 17}
  t2 t2_idx_00000063 {100 20} 
  t2 t2_idx_00000064 {100 5} 
  t2 t2_idx_0001295b {100 20 5}
}

finish_test

Changes to ext/fts3/fts3.c.
322
323
324
325
326
327
328

329

330
331
332
333
334
335
336
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338







+

+








/*
** This variable is set to false when running tests for which the on disk
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
#ifdef SQLITE_DEBUG
int sqlite3_fts3_may_be_corrupt = 1;
#endif

/* 
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
1893
1894
1895
1896
1897
1898
1899
1900

1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917


1918
1919
1920
1921
1922
1923
1924
1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917


1918
1919
1920
1921
1922
1923
1924
1925
1926







-
+















-
-
+
+







){
  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 */
  sqlite3_int64 iChild;           /* Block id of child node to descend to */
  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 += sqlite3Fts3GetVarint(zCsr, &iChild);
  zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
  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 */
1963
1964
1965
1966
1967
1968
1969
1970

1971
1972
1973
1974
1975

1976
1977
1978
1979
1980
1981
1982
1983


1984
1985
1986
1987
1988
1989
1990
1965
1966
1967
1968
1969
1970
1971

1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983


1984
1985
1986
1987
1988
1989
1990
1991
1992







-
+




-
+






-
-
+
+







    ** 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 = iChild;
      *piFirst = (i64)iChild;
      piFirst = 0;
    }

    if( piLast && cmp<0 ){
      *piLast = iChild;
      *piLast = (i64)iChild;
      piLast = 0;
    }

    iChild++;
  };

  if( piFirst ) *piFirst = iChild;
  if( piLast ) *piLast = iChild;
  if( piFirst ) *piFirst = (i64)iChild;
  if( piLast ) *piLast = (i64)iChild;

 finish_scan:
  sqlite3_free(zBuffer);
  return rc;
}


3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592




3593
3594


3595
3596



3597
3598
3599
3600
3601
3602
3603
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599


3600
3601


3602
3603
3604
3605
3606
3607
3608
3609
3610
3611







+




+
+
+
+
-
-
+
+
-
-
+
+
+







}

/*
** Implementation of xBegin() method. 
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
  Fts3Table *p = (Fts3Table*)pVtab;
  int rc;
  UNUSED_PARAMETER(pVtab);
  assert( p->pSegments==0 );
  assert( p->nPendingData==0 );
  assert( p->inTransaction!=1 );
  p->nLeafAdd = 0;
  rc = fts3SetHasStat(p);
#ifdef SQLITE_DEBUG
  if( rc==SQLITE_OK ){
  TESTONLY( p->inTransaction = 1 );
  TESTONLY( p->mxSavepoint = -1; );
    p->inTransaction = 1;
    p->mxSavepoint = -1;
  p->nLeafAdd = 0;
  return fts3SetHasStat(p);
  }
#endif
  return rc;
}

/*
** Implementation of xCommit() method. This is a no-op. The contents of
** the pending-terms hash-table have already been flushed into the database
** by fts3SyncMethod().
*/
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134

5135
5136
5137
5138
5139
5140
5141
5126
5127
5128
5129
5130
5131
5132

5133
5134
5135
5136

5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148







-




-




+







  /* 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;
    Fts3Expr **apOr;
    aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
        sizeof(Fts3TokenAndCost) * nToken
      + sizeof(Fts3Expr *) * nOr * 2
    );
    apOr = (Fts3Expr **)&aTC[nToken];

    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);
Changes to ext/fts3/fts3Int.h.
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144







-
+







#define POS_END     (0)     /* Position-list terminator */ 

/*
** The assert_fts3_nc() macro is similar to the assert() macro, except that it
** is used for assert() conditions that are true only if it can be 
** guranteed that the database is not corrupt.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
#ifdef SQLITE_DEBUG
extern int sqlite3_fts3_may_be_corrupt;
# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
#else
# define assert_fts3_nc(x) assert(x)
#endif

/*
Changes to ext/fts3/fts3_aux.c.
402
403
404
405
406
407
408

409
410
411
412
413
414
415
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416







+







  }

  /* 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]);
Changes to ext/fts3/fts3_snippet.c.
13
14
15
16
17
18
19




20
21
22
23
24
25
26
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30







+
+
+
+








#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 */
63
64
65
66
67
68
69
70

71
72

73
74
75
76
77
78
79
67
68
69
70
71
72
73

74
75

76
77
78
79
80
81
82
83







-
+

-
+







  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 */
  int iHead;                      /* Next value in position list */
  i64 iHead;                      /* Next value in position list */
  char *pHead;                    /* Position list data following iHead */
  int iTail;                      /* Next value in trailing position list */
  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 */
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
234
235
236
237
238
239
240

241
242
243
244
245
246
247
248







-
+







** 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, int *piPos){
static void fts3GetDeltaPosition(char **pp, i64 *piPos){
  int iVal;
  *pp += fts3GetVarint32(*pp, &iVal);
  *piPos += (iVal-2);
}

/*
** Helper function for fts3ExprIterate() (see below).
339
340
341
342
343
344
345
346

347
348
349

350
351
352
353
354
355
356
343
344
345
346
347
348
349

350
351
352

353
354
355
356
357
358
359
360







-
+


-
+







}

/*
** 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, int *piIter, int iNext){
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
  char *pIter = *ppIter;
  if( pIter ){
    int iIter = *piIter;
    i64 iIter = *piIter;

    while( iIter<iNext ){
      if( 0==(*pIter & 0xFE) ){
        iIter = -1;
        pIter = 0;
        break;
      }
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443







-
+







  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;
      int iCsr = pPhrase->iTail;
      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 );
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
475
476
477
478
479
480
481

482
483
484
485
486
487
488
489







-
+







  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 ){
    int iFirst = 0;
    i64 iFirst = 0;
    pPhrase->pList = pCsr;
    fts3GetDeltaPosition(&pCsr, &iFirst);
    if( iFirst<0 ){
      rc = FTS_CORRUPT_VTAB;
    }else{
      pPhrase->pHead = pCsr;
      pPhrase->pTail = pCsr;
1535
1536
1537
1538
1539
1540
1541
1542
1543


1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564
1565
1566
1567
1568
1569
1539
1540
1541
1542
1543
1544
1545


1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
1573







-
-
+
+


















-
+









typedef struct TermOffset TermOffset;
typedef struct TermOffsetCtx TermOffsetCtx;

struct TermOffset {
  char *pList;                    /* Position-list */
  int iPos;                       /* Position just read from pList */
  int iOff;                       /* Offset of this term from read positions */
  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 */
  int iPos = 0;                   /* First position in position-list */
  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);
Changes to ext/fts3/fts3_test.c.
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609







+













+







*/
static int SQLITE_TCLAPI fts3_may_be_corrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_DEBUG
  int bOld = sqlite3_fts3_may_be_corrupt;

  if( objc!=2 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
    return TCL_ERROR;
  }
  if( objc==2 ){
    int bNew;
    if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
    sqlite3_fts3_may_be_corrupt = bNew;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
#endif
  return TCL_OK;
}

int Sqlitetestfts3_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
  Tcl_CreateObjCommand(interp, 
      "fts3_configure_incr_load", fts3_configure_incr_load_cmd, 0, 0
Changes to ext/fts3/fts3_write.c.
1803
1804
1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817







-
+







    }
  }else{
    rc = (pLhs->aNode==0) - (pRhs->aNode==0);
  }
  if( rc==0 ){
    rc = pRhs->iIdx - pLhs->iIdx;
  }
  assert( rc!=0 );
  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:
Changes to ext/fts5/fts5_config.c.
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
533
534
535
536
537
538
539

540
541
542
543
544
545
546
547







-
+







  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 = (u8*)&pRet->azCol[nArg];
  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
Changes to ext/fts5/fts5_expr.c.
2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422







+







      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){
2774
2775
2776
2777
2778
2779
2780

2781
2782
2783
2784
2785
2786

2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803




2804
2805
2806
2807
2808
2809
2810
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
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







+






+

















+
+
+
+







    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.
*/
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;
Changes to ext/fts5/fts5_index.c.
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441







-
+







*/
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) */
  int iLeafOffset;                /* Byte offset within current leaf */
  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;
1607
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619
1620
1621
1607
1608
1609
1610
1611
1612
1613

1614
1615
1616
1617
1618
1619
1620
1621







-
+







    }
    pIter->iLeafOffset = iOff;
  }
}

static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
  u8 *a = pIter->pLeaf->p;        /* Buffer to read data from */
  int iOff = pIter->iLeafOffset;
  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;
1640
1641
1642
1643
1644
1645
1646
1647

1648
1649
1650
1651
1652
1653
1654
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650
1651
1652
1653
1654







-
+







**
** 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 */
  int iOff = pIter->iLeafOffset;  /* Offset to read at */
  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;
  }
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081







-







        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( p->rc==SQLITE_OK );
      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 );
    }
  }
4537
4538
4539
4540
4541
4542
4543
4544

4545
4546
4547
4548
4549
4550
4551

4552
4553
4554
4555
4556
4557
4558
4536
4537
4538
4539
4540
4541
4542

4543
4544
4545
4546
4547
4548
4549

4550
4551
4552
4553
4554
4555
4556
4557







-
+






-
+








      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;
        i64 iDelta = 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], (u64*)&iDelta);
          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);
5075
5076
5077
5078
5079
5080
5081

5082

5083
5084
5085
5086
5087
5088
5089
5074
5075
5076
5077
5078
5079
5080
5081

5082
5083
5084
5085
5086
5087
5088
5089







+
-
+








      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 );
      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 ){
6222
6223
6224
6225
6226
6227
6228

6229
6230
6231
6232
6233
6234
6235
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236







+








/*************************************************************************
**************************************************************************
** Below this point is the implementation of the fts5_decode() scalar
** function only.
*/

#ifdef SQLITE_TEST
/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
*/
static void fts5DecodeRowid(
  i64 iRowid,                     /* Rowid from %_data table */
  int *piSegid,                   /* OUT: Segment id */
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
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







+

+

















+

+







  iRowid >>= FTS5_DATA_HEIGHT_B;

  *pbDlidx = (int)(iRowid & 0x0001);
  iRowid >>= FTS5_DATA_DLI_B;

  *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
  int iSegid, iHeight, iPgno, bDlidx;       /* Rowid compenents */
  fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);

  if( iSegid==0 ){
    if( iKey==FTS5_AVERAGES_ROWID ){
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} ");
    }else{
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}");
    }
  }
  else{
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}",
        bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno
    );
  }
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
static void fts5DebugStructure(
  int *pRc,                       /* IN/OUT: error code */
  Fts5Buffer *pBuf,
  Fts5Structure *p
){
  int iLvl, iSeg;                 /* Iterate through levels, segments */

6284
6285
6286
6287
6288
6289
6290

6291

6292
6293
6294
6295
6296
6297
6298
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305







+

+







      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", 
          pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
      );
    }
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
  }
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
** function appends a human-readable representation of the same object
** to the buffer passed as the second argument. 
*/
6309
6310
6311
6312
6313
6314
6315

6316

6317
6318
6319
6320
6321
6322
6323
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332







+

+







    *pRc = rc;
    return;
  }

  fts5DebugStructure(pRc, pBuf, p);
  fts5StructureRelease(p);
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain an "averages" record. This function 
** appends a human-readable representation of record to the buffer passed 
** as the second argument. 
*/
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
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







+

+
















+

+







  while( i<nBlob ){
    u64 iVal;
    i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
    zSpace = " ";
  }
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
** after either the input buffer is exhausted or a 0 value is read.
**
** The return value is the number of bytes read from the input buffer.
*/
static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
  int iOff = 0;
  while( iOff<n ){
    int iVal;
    iOff += fts5GetVarint32(&a[iOff], iVal);
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %d", iVal);
  }
  return iOff;
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
** representation of the part of the doclist that is present to buffer
** pBuf. 
**
** The return value is the number of bytes read from the input buffer.
6382
6383
6384
6385
6386
6387
6388

6389

6390
6391
6392
6393
6394
6395
6396
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411







+

+







      iDocid += iDelta;
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
    }
  }

  return iOff;
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is 
** only ever used with detail=none tables.
**
** Buffer (pData/nData) contains a doclist in the format used by detail=none
** tables. This function appends a human-readable version of that list to
** buffer pBuf.
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







+

+







        zApp = "*";
      }
    }

    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
  }
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args (always 2) */
  sqlite3_value **apVal           /* Function arguments */
6632
6633
6634
6635
6636
6637
6638

6639

6640
6641
6642
6643
6644
6645
6646
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665







+

+







  if( rc==SQLITE_OK ){
    sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
  }else{
    sqlite3_result_error_code(pCtx, rc);
  }
  fts5BufferFree(&s);
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST 
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
static void fts5RowidFunction(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args (always 2) */
  sqlite3_value **apVal           /* Function arguments */
6666
6667
6668
6669
6670
6671
6672

6673
6674
6675
6676
6677
6678
6679
6680
6681
6682

6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699




6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6685
6686
6687
6688
6689
6690
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
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734







+










+

















+
+
+
+










    }else{
      sqlite3_result_error(pCtx, 
        "first arg to fts5_rowid() must be 'segment'" , -1
      );
    }
  }
}
#endif /* SQLITE_TEST */

/*
** This is called as part of registering the FTS5 module with database
** connection db. It registers several user-defined scalar functions useful
** with FTS5.
**
** If successful, SQLITE_OK is returned. If an error occurs, some other
** SQLite error code is returned instead.
*/
int sqlite3Fts5IndexInit(sqlite3 *db){
#ifdef SQLITE_TEST
  int rc = sqlite3_create_function(
      db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
  );

  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(
        db, "fts5_decode_none", 2, 
        SQLITE_UTF8, (void*)db, fts5DecodeFunction, 0, 0
    );
  }

  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(
        db, "fts5_rowid", -1, SQLITE_UTF8, 0, fts5RowidFunction, 0, 0
    );
  }
  return rc;
#else
  return SQLITE_OK;
  UNUSED_PARAM(db);
#endif
}


int sqlite3Fts5IndexReset(Fts5Index *p){
  assert( p->pStruct==0 || p->iStructVersion!=0 );
  if( fts5IndexDataVersion(p)!=p->iStructVersion ){
    fts5StructureInvalidate(p);
  }
  return fts5IndexReturn(p);
}
Changes to ext/fts5/fts5_main.c.
18
19
20
21
22
23
24

25

26
27
28
29
30
31
32
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34







+

+








/*
** This variable is set to false when running tests for which the on disk
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts5 code are activated - conditions that are
** only true if it is guaranteed that the fts5 database is not corrupt.
*/
#ifdef SQLITE_DEBUG
int sqlite3_fts5_may_be_corrupt = 1;
#endif


typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
Changes to ext/fts5/fts5_tcl.c.
25
26
27
28
29
30
31

32

33
34
35
36
37
38
39
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41







+

+








#ifdef SQLITE_ENABLE_FTS5

#include "fts5.h"
#include <string.h>
#include <assert.h>

#ifdef SQLITE_DEBUG
extern int sqlite3_fts5_may_be_corrupt;
#endif
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*);

/*************************************************************************
** This is a copy of the first part of the SqliteDb structure in 
** tclsqlite.c.  We need it here so that the get_sqlite_pointer routine
** can extract the sqlite3* pointer from an existing Tcl SQLite
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030
1031
1032
1033
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037







+













+







*/
static int SQLITE_TCLAPI f5tMayBeCorrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_DEBUG
  int bOld = sqlite3_fts5_may_be_corrupt;

  if( objc!=2 && objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
    return TCL_ERROR;
  }
  if( objc==2 ){
    int bNew;
    if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
    sqlite3_fts5_may_be_corrupt = bNew;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
#endif
  return TCL_OK;
}


static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){
  int i;
  unsigned int h = 13;
Changes to ext/fts5/test/fts5corrupt3.test.
14587
14588
14589
14590
14591
14592
14593










































































































































































































































































































































14594
14595
14596
14597
14598
14587
14588
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640
14641
14642
14643
14644
14645
14646
14647
14648
14649
14650
14651
14652
14653
14654
14655
14656
14657
14658
14659
14660
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670
14671
14672
14673
14674
14675
14676
14677
14678
14679
14680
14681
14682
14683
14684
14685
14686
14687
14688
14689
14690
14691
14692
14693
14694
14695
14696
14697
14698
14699
14700
14701
14702
14703
14704
14705
14706
14707
14708
14709
14710
14711
14712
14713
14714
14715
14716
14717
14718
14719
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748
14749
14750
14751
14752
14753
14754
14755
14756
14757
14758
14759
14760
14761
14762
14763
14764
14765
14766
14767
14768
14769
14770
14771
14772
14773
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900
14901
14902
14903
14904
14905
14906
14907
14908
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+





| end x.db
}]} {}

do_catchsql_test 74.1 {
  SELECT rowid, quote(matchinfo(t1,'p�xyb<s')) FROM t1 WHERE t1 MATCH 'e*';
} {1 {unable to use function matchinfo in the requested context}}

#-------------------------------------------------------------------------
reset_db
do_test 75.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 32768 pagesize 4096 filename crash-033d665d5caa8d.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00   .....@  ........
|     96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36   ...............6
|    112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 00 00 00 00   ...k............
|   3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74   .........1tablet
|   3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45   2t2.CREATE TABLE
|   3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61    t2(x)V.......ta
|   3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63   blet1_configt1_c
|   3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42   onfig.CREATE TAB
|   3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b   LE 't1_config'(k
|   3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29    PRIMARY KEY, v)
|   3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06    WITHOUT ROWID[.
|   3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64   ..!!...tablet1_d
|   3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65   ocsizet1_docsize
|   3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74   .CREATE TABLE 't
|   3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e   1_docsize'(id IN
|   3664: 54 45 47 45 52 20 50 52 49 4d 54 52 59 20 4b 45   TEGER PRIMTRY KE
|   3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21   Y, sz BLOB)^...!
|   3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74   !...tablet1_cont
|   3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52   entt1_content.CR
|   3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63   EATE TABLE 't1_c
|   3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47   ontent'(id INTEG
|   3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   ER PRIMARY KEY, 
|   3776: 63 30 2c 20 63 31 2c d6 63 32 29 69 04 07 17 19   c0, c1,.c2)i....
|   3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74   ...-tablet1_idxt
|   3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42   1_idx.CREATE TAB
|   3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69   LE 't1_idx'(segi
|   3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50   d, term, pgno, P
|   3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64   RIMARY KEY(segid
|   3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54   , term)) WITHOUT
|   3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74    ROWIDU........t
|   3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61   ablet1_datat1_da
|   3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20   ta.CREATE TABLE 
|   3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54   't1_data'(id INT
|   3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59   EGER PRIMARY KEY
|   3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06   , block BLOB)8..
|   3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52   ...._tablet1t1CR
|   4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35   LE t1 USING fts5
|   4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00   (a,b,c).........
| page 3 offset 8192
|      0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00   ................
|   3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18   .....J..........
|   3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06   ...+.00.........
|   3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30   ...........21160
|   3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1   609...........3.
|   3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 01 02   ..........5.....
|   3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 3d   ......0000000..=
|   3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06   ........binary..
|   3328: 01 02 02 03 06 01 01 f2 03 06 4e 02 02 03 06 01   ..........N.....
|   3344: 02 02 03 05 01 02 02 03 06 01 02 02 03 06 01 02   ................
|   3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02   ................
|   3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70   ............comp
|   3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64   iler...........d
|   3408: 62 73 74 61 74 07 02 03 01 02 13 01 02 03 02 04   bstat...........
|   3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 07 65   ebug...........e
|   3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02   nable...........
|   3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02   ................
|   3472: 01 02 02 01 02 02 01 02 01 f1 02 02 01 02 02 01   ................
|   3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02   ................
|   3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02   ......xtension..
|   3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03   .........fts4...
|   3536: 01 02 03 01 02 03 04 01 25 0d 02 03 01 02 03 01   ........%.......
|   3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03   ....gcc.........
|   3568: 02 06 65 6f 70 6f 6c 79 0f f2 03 01 02 03 01 02   ..eopoly........
|   3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02   ...json1........
|   3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03   ...load.........
|   3616: 00 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05   ..max...........
|   3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04   emory...........
|   3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e   sys5...........n
|   3664: 6f 63 61 73 65 02 06 01 02 02 13 06 00 f2 02 03   ocase...........
|   3680: 06 01 02 02 13 06 01 02 02 03 06 01 02 02 03 06   ................
|   3696: 01 02 02 03 06 01 02 02 03 06 02 02 02 03 06 01   ................
|   3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02   ................
|   3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 b2   ...omit.........
|   3744: 01 0a 22 74 72 65 65 19 02 03 01 02 03 01 02 03   ...tree.........
|   3760: 04 02 69 6c f1 06 01 02 02 03 06 01 02 02 03 06   ..il............
|   3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01   ................
|   3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02   ................
|   3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02   ................
|   3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01   ..threadsafe....
|   3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02   .......vtab.....
|   3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01   ......x.........
|   3872: 02 01 06 01 01 02 04 36 01 01 02 01 06 01 01 02   .......6........
|   3888: 01 06 01 11 02 01 06 01 01 02 01 06 01 01 02 01   ................
|   3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06   ................
|   3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01   ................
|   3936: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01   ................
|   3952: 02 01 06 01 01 01 f1 06 01 01 02 ad 06 01 01 02   ................
|   3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01   ................
|   3984: 06 01 01 01 01 06 01 01 02 01 06 01 01 02 01 06   ................
|   4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01   ................
|   4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01   ................
|   4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c   ................
|   4048: 12 44 13 11 0f 47 13 0e fc 0e 11 10 0f 0e 10 0f   .D...G..........
|   4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f   D..@.......$Z$$.
|   4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01   ...$............
| page 4 offset 12288
|      0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02   ................
| page 5 offset 16384
|      0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f   ...........$..%.
|   3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49   .THREADSAFE=0XBI
|   3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41   NARY.#..%..THREA
|   3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 8f   DSAFE=0XNOCASE..
|   3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 45 3d   ..%..THREADSAFE=
|   3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 45 ed   0XRTRIM.!..3..E.
|   3168: 49 54 20 4c 4f 41 44 21 45 58 54 45 4e 53 49 4f   IT LOAD!EXTENSIO
|   3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f   NXBINARY. ..3..O
|   3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 5a 29   MIT LOAD EXTENZ)
|   3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17   ONXNOCASE....3..
|   3232: 4f 4d 59 54 20 4c 4f 41 44 20 45 58 54 45 4e 53   OMYT LOAD EXTENS
|   3248: 49 4f 4e 58 52 54 56 a9 4d 1f 1e 05 00 33 0f 19   IONXRTV.M....3..
|   3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 25 30 30 30 30   MAX MEMORY=%0000
|   3280: 30 30 30 57 42 49 4e 31 52 59 1f 1d 05 00 33 0f   000WBIN1RY....3.
|   3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30   .MAX MEMORY=5000
|   3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 32   0000XNOCASE....2
|   3328: 0e 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30   ..NAX MEMORY-500
|   3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25   00000XRTRIM....%
|   3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42   ..ENABLE RTREEXB
|   3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42   INARY....%..ENAB
|   3392: 4c 45 20 52 54 52 45 45 59 4e 4f 43 41 53 45 17   LE RTREEYNOCASE.
|   3408: 19 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52   .f.%..ENABLE RTR
|   3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45   EEXRTRIM....)..E
|   3440: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49   NABLE MEMSYS5XBI
|   3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c   NARY....)..ENABL
|   3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45   E MEMSYS5XNOCASE
|   3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45   ....)..ENABLE ME
|   3504: 4d 53 59 76 35 58 52 54 52 49 4d 18 15 05 10 25   MSYv5XRTRIM....%
|   3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42   ..EN@BLE JSON1XB
|   3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42   INARY....%..ENAB
|   3552: 4c 45 20 4a 53 4f 4e 32 58 4e 4f 43 41 53 45 17   LE JSON2XNOCASE.
|   3568: 13 05 00 25 0f 17 45 4e 41 42 4c 45 20 4a 53 4f   ...%..ENABLE JSO
|   3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45   N1XRTRIM....)..E
|   3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49   NABLE GEOPOLYXBI
|   3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 5f 81 42 4c   NARY....)..E_.BL
|   3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 51 53 45   E GEOPOLYXNOCQSE
|   3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45   ....)..ENABLE GE
|   3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23   OPOLYXRTRIM....#
|   3680: 0f 1a 45 4e 41 42 4c 45 20 56 54 43 35 58 42 49   ..ENABLE VTC5XBI
|   3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c   NARY....#..ENABL
|   3712: 45 20 46 54 53 35 48 4e 4f 43 41 53 45 16 1d 05   E FTS5HNOCASE...
|   3728: 00 23 0f a4 45 4e 41 42 4c 45 20 46 54 53 35 58   .#..ENABLE FTS5X
|   3744: 52 54 52 49 4d b7 0c 05 00 23 0f 19 45 4e 41 42   RTRIM....#..ENAB
|   3760: 4c 45 20 46 55 53 34 58 42 49 4e 41 52 59 17 0b   LE FUS4XBINARY..
|   3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34   ..#..ENABLE FTS4
|   3792: 57 4e 4f 43 41 53 45 16 0a 05 00 21 7f 17 45 4e   WNOCASE....!..EN
|   3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e   ABLE FTS4.RTRIM.
|   3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
|   3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e   TAT VTABXBINARY.
|   3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
|   3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d   TAT VTABXNOCASE.
|   3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53   ...1..ENABLE DBS
|   3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06   TAT VTABXRTRIM..
|   3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52   .....DEBUGXBINAR
|   3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f   Y.......DEBUGXNO
|   3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47   CASE.......DEBUG
|   3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d   XRTRIM'...C..COM
|   3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20   PILER=gcc-5.4.0 
|   4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27   20160609XBINARY'
|   4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3f 87   ...C..COMPILER?.
|   4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30   cc-5.4.0 2016060
|   4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 00   9XNOCASE&...C...
| page 6 offset 20480
|   3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01   .$.......#......
|   3824: 06 22 03 01 12 02 01 01 06 21 03 00 12 03 01 01   .........!......
|   3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 02 01   . ..............
|   3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01   ................
|   3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01   ................
|   3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01   ................
|   3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01   ................
|   3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01   ................
|   3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01   ................
|   3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01   ................
|   3968: 06 00 03 00 12 02 01 01 06 0f 03 00 12 02 01 01   ................
|   3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01   ................
|   4000: 06 0c 03 00 12 02 01 01 06 0b 03 10 12 02 01 01   ................
|   4016: 06 0a 03 00 12 02 01 01 06 09 03 01 12 03 01 01   ................
|   4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01   ................
|   4048: 07 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01   ................
|   4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01   ................
|   4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01   ................
| page 7 offset 24576
|      0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04   ........version.
| page 8 offset 28672
|   4048: 00 00 00 00 00 00 5d 03 02 2b 69 6e 74 00 00 00   ......]..+int...
| end crash-033d665d5caa8d.db
}]} {}

do_catchsql_test 75.1 {
  SELECT rowid, quote(matchinfo(t1,'pcxybs')) FROM t1 WHERE t1 MATCH 'e*';
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
reset_db
do_test 76.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 40960 pagesize 4096 filename crash-03b68c01d30713.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 0a   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 0d 00 00 00 04   ................
|     96: 00 00 00 00 0d 00 00 00 0d 0b 6e 00 0f a3 0f 4c   ..........n....L
|    112: 0e e1 0e 81 0e 24 0d cc 0d 72 0d 1b 0c b0 0c 50   .....$...r.....P
|    128: 0b f8 0b b3 0b 6e 01 00 00 00 00 00 00 00 00 00   .....n..........
|   2912: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 0d   ..............C.
|   2928: 06 17 11 11 08 75 74 61 62 6c 65 74 34 74 34 43   .....utablet4t4C
|   2944: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41   REATE VIRTUAL TA
|   2960: 42 4c 45 20 74 34 20 55 53 49 4e 47 20 66 74 73   BLE t4 USING fts
|   2976: 35 76 6f 63 61 62 28 27 74 32 27 2c 20 27 72 6f   5vocab('t2', 'ro
|   2992: 77 27 29 43 0c 06 17 11 11 08 75 74 61 62 6c 65   w')C......utable
|   3008: 74 33 74 33 43 52 45 41 54 45 20 56 49 52 54 55   t3t3CREATE VIRTU
|   3024: 41 4c 20 54 41 42 4c 45 20 74 33 20 55 53 49 4e   AL TABLE t3 USIN
|   3040: 47 20 66 74 73 35 76 6f 63 61 62 28 27 74 31 27   G fts5vocab('t1'
|   3056: 2c 20 27 72 6f 77 27 29 56 0b 06 17 1f 1f 01 7d   , 'row')V.......
|   3072: 74 61 62 6c 65 74 32 5f 63 6f 6e 66 69 67 74 32   tablet2_configt2
|   3088: 5f 63 6f 6e 66 69 67 0a 43 52 45 41 54 45 20 54   _config.CREATE T
|   3104: 41 42 4c 45 20 27 74 32 5f 63 6f 6e 66 69 67 27   ABLE 't2_config'
|   3120: 28 6b 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20   (k PRIMARY KEY, 
|   3136: 76 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44   v) WITHOUT ROWID
|   3152: 5e 0a 07 17 21 21 01 81 07 74 61 62 6c 65 74 32   ^...!!...tablet2
|   3168: 5f 63 6f 6e 74 65 6e 74 74 32 5f 63 6f 6e 74 65   _contentt2_conte
|   3184: 6e 74 09 43 52 45 41 54 45 20 54 41 42 4c 45 20   nt.CREATE TABLE 
|   3200: 27 74 32 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20   't2_content'(id 
|   3216: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20   INTEGER PRIMARY 
|   3232: 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32 29   KEY, c0, c1, c2)
|   3248: 69 09 07 17 19 19 01 81 2d 74 61 62 6c 65 74 32   i.......-tablet2
|   3264: 5f 69 64 78 74 32 5f 69 64 78 08 43 52 45 41 54   _idxt2_idx.CREAT
|   3280: 45 20 54 41 42 4c 45 20 27 74 32 5f 69 64 78 27   E TABLE 't2_idx'
|   3296: 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67   (segid, term, pg
|   3312: 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28   no, PRIMARY KEY(
|   3328: 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49   segid, term)) WI
|   3344: 54 48 4f 55 54 20 52 4f 57 49 44 55 08 07 17 1b   THOUT ROWIDU....
|   3360: 1b 01 81 01 74 61 62 6c 65 74 32 5f 64 61 74 61   ....tablet2_data
|   3376: 74 32 5f 64 61 74 61 07 43 52 45 41 54 45 20 54   t2_data.CREATE T
|   3392: 41 42 4c 45 20 27 74 32 5f 64 61 74 61 27 28 69   ABLE 't2_data'(i
|   3408: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52   d INTEGER PRIMAR
|   3424: 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f   Y KEY, block BLO
|   3440: 42 29 58 07 07 17 11 11 08 81 1d 74 61 62 6c 65   B)X........table
|   3456: 74 32 74 32 43 52 45 41 54 45 20 56 49 52 54 55   t2t2CREATE VIRTU
|   3472: 41 4c 20 54 41 42 4c 45 20 74 32 20 55 53 49 4e   AL TABLE t2 USIN
|   3488: 47 20 66 74 73 35 28 27 61 27 2c 5b 62 5d 2c 22   G fts5('a',[b],.
|   3504: 63 22 2c 64 65 74 61 69 6c 3d 6e 6f 6e 65 2c 63   c.,detail=none,c
|   3520: 6f 6c 75 6d 6e 73 69 7a 65 3d 30 29 56 06 06 17   olumnsize=0)V...
|   3536: 1f 1f 01 7d 74 61 62 6c 65 74 31 5f 63 6f 6e 66   ....tablet1_conf
|   3552: 69 67 74 31 5f 63 6f 6e 66 69 67 06 43 52 45 41   igt1_config.CREA
|   3568: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 6f 6e   TE TABLE 't1_con
|   3584: 66 69 67 27 28 6b 20 50 52 49 4d 41 52 59 20 4b   fig'(k PRIMARY K
|   3600: 45 59 2c 20 76 29 20 57 49 54 48 4f 55 54 20 52   EY, v) WITHOUT R
|   3616: 4f 57 49 44 5b 05 07 17 21 21 01 81 01 74 61 62   OWID[...!!...tab
|   3632: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64   let1_docsizet1_d
|   3648: 6f 63 73 69 7a 65 05 43 52 45 41 54 45 20 54 41   ocsize.CREATE TA
|   3664: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27   BLE 't1_docsize'
|   3680: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   (id INTEGER PRIM
|   3696: 41 52 59 20 4b 45 59 2c 20 73 7a 20 42 4c 4f 42   ARY KEY, sz BLOB
|   3712: 29 5e 04 07 17 21 21 01 81 07 74 61 62 6c 65 74   )^...!!...tablet
|   3728: 31 5f 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74   1_contentt1_cont
|   3744: 65 6e 74 04 43 52 45 41 54 45 20 54 41 42 4c 45   ent.CREATE TABLE
|   3760: 20 27 74 31 5f 63 6f 6e 74 65 6e 74 27 28 69 64    't1_content'(id
|   3776: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3792: 20 4b 45 59 2c 20 63 30 2c 20 63 31 2c 20 63 32    KEY, c0, c1, c2
|   3808: 29 69 03 07 17 19 19 01 81 2d 74 61 62 6c 65 74   )i.......-tablet
|   3824: 31 5f 69 64 78 74 31 5f 69 64 78 03 43 52 45 41   1_idxt1_idx.CREA
|   3840: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 69 64 78   TE TABLE 't1_idx
|   3856: 27 28 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70   '(segid, term, p
|   3872: 67 6e 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59   gno, PRIMARY KEY
|   3888: 28 73 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57   (segid, term)) W
|   3904: 49 54 48 4f 55 54 20 52 4f 57 49 44 55 02 07 17   ITHOUT ROWIDU...
|   3920: 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 64 61 74   .....tablet1_dat
|   3936: 61 74 31 5f 64 61 74 61 02 43 52 45 41 54 45 20   at1_data.CREATE 
|   3952: 54 41 42 4c 45 20 27 74 31 5f 64 61 74 61 27 28   TABLE 't1_data'(
|   3968: 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41   id INTEGER PRIMA
|   3984: 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 4c   RY KEY, block BL
|   4000: 4f 42 29 5b 01 07 17 11 11 08 81 23 74 61 62 6c   OB)[.......#tabl
|   4016: 65 74 31 74 31 43 52 45 41 54 45 20 56 49 52 54   et1t1CREATE VIRT
|   4032: 55 41 4c 20 54 41 42 4c 45 20 74 31 20 55 53 49   UAL TABLE t1 USI
|   4048: 4e 47 20 66 74 73 35 28 61 2c 62 20 75 6e 69 65   NG fts5(a,b unie
|   4064: 24 65 78 65 64 2c 63 2c 74 6f 6b 65 6e 69 7a 65   $exed,c,tokenize
|   4080: 3d 22 70 6f 72 74 65 72 20 61 73 63 69 69 22 29   =.porter ascii.)
| page 2 offset 4096
|      0: 0d 0f 68 00 05 0f 13 00 0f e6 0f 13 0f a8 00 00   ..h.............
|   3856: 00 00 00 15 0a 03 00 30 00 00 00 00 01 03 03 00   .......0........
|   3872: 03 01 01 01 02 01 01 03 01 01 37 8c 80 80 80 80   ..........7.....
|   3888: 01 03 00 74 00 20 68 20 69 0d 00 00 00 03 0f e8   ...t. h i.......
| page 5 offset 16384
|   4064: 00 00 00 00 00 00 00 00 06 03 03 00 12 03 00 00   ................
|   4080: 60 20 30 d6 20 30 00 30 60 10 30 01 20 30 00 30   ` 0. 0.0`.0. 0.0
| page 6 offset 20480
|      0: a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04   ........version.
| page 7 offset 24576
|      0: 0d 00 00 00 03 0f 9e 00 0f e6 0f ef 0f 9e 00 00   ................
|     16: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3984: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 84   ..............A.
|   4000: 80 80 80 80 01 04 00 81 06 00 00 00 34 02 30 61   ............4.0a
|   4016: 01 00 ff ff ff ff ff ff ff ff ff 11 87 89 06 26   ...............&
|   4032: 01 64 01 01 01 65 01 01 01 66 01 01 01 66 01 01   .d...e...f...f..
|   4048: 01 01 01 68 01 01 01 01 01 69 01 01 01 04 01 56   ...h.....i.....V
|   4064: 06 04 44 00 06 06 07 01 03 00 14 03 09 09 09 0f   ..D.............
|   4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01   ...$............
| page 8 offset 28672
|      0: 0a 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 1c 01 02   ................
| page 9 offset 32768
|      0: 0d 00 00 00 9d 0f be 00 0f ea 0f d4 0f be 00 00   ................
|   4016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 03   ................
|   4032: 05 00 17 17 17 61 20 62 20 63 67 20 68 20 69 67   .....a b cg h ig
|   4048: 20 68 20 69 14 02 05 00 17 17 17 67 20 68 20 69    h i.......g h i
|   4064: 61 20 62 20 63 67 20 68 20 69 14 01 04 ff 17 17   a b cg h i......
|   4080: 17 61 20 62 20 63 64 20 65 20 66 67 20 68 20 69   .a b cd e fg h i
| page 10 offset 36864
|      0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 01   ................
|   4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04   ........version.
| end crash-03b68c01d30713.db
}]} {}


do_catchsql_test 76.1 {
  SELECT * FROM t4;
} {1 {database disk image is malformed}}


sqlite3_fts5_may_be_corrupt 0
finish_test

Changes to ext/fts5/test/fts5doclist.test.
38
39
40
41
42
43
44





















45
46
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  INSERT INTO ccc(x899) SELECT rnddoc(500) FROM ii;
}

do_execsql_test 1.2 {
  INSERT INTO ccc(ccc) VALUES('integrity-check');
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.1 {
  CREATE VIRTUAL TABLE tx USING fts5(x);
}

set doc [string repeat "abc " 5000]
do_execsql_test 2.2 {
  BEGIN;
    INSERT INTO tx(rowid, x) VALUES(-9000000000000000000, $doc);
    INSERT INTO tx(rowid, x) VALUES(9000000000000000000, $doc);
  COMMIT;
}

do_execsql_test 2.3 {
  SELECT rowid FROM tx('abc');
} {
  -9000000000000000000
   9000000000000000000
}

finish_test
Changes to ext/fts5/test/fts5plan.test.
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
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







-
-
+
+






-
-
+
+






-
+







-
+





-
+


  CREATE VIRTUAL TABLE f1 USING fts5(ff);
}

do_eqp_test 1.1 {
  SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
  |--SCAN t1
  `--SCAN f1 VIRTUAL TABLE INDEX 0:M1
}

do_eqp_test 1.2 {
  SELECT * FROM t1, f1 WHERE f1 > t1.x
} {
  QUERY PLAN
  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
  `--SCAN TABLE t1
  |--SCAN f1 VIRTUAL TABLE INDEX 0:
  `--SCAN t1
}

do_eqp_test 1.3 {
  SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
  QUERY PLAN
  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:M1
  |--SCAN f1 VIRTUAL TABLE INDEX 0:M1
  `--USE TEMP B-TREE FOR ORDER BY
}

do_eqp_test 1.4 {
  SELECT * FROM f1 ORDER BY rank
} {
  QUERY PLAN
  |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
  |--SCAN f1 VIRTUAL TABLE INDEX 0:
  `--USE TEMP B-TREE FOR ORDER BY
}

do_eqp_test 1.5 {
  SELECT * FROM f1 WHERE rank MATCH ?
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
} {SCAN f1 VIRTUAL TABLE INDEX 0:r}

finish_test
Changes to ext/fts5/test/fts5trigram.test.
188
189
190
191
192
193
194
195

196
197
198
199
200
201
188
189
190
191
192
193
194

195
196
197
198
199
200








-
+





-
  SELECT * FROM ci0 WHERE x LIKE ?
} {VIRTUAL TABLE INDEX 0:L0}
do_eqp_test 6.2 {
  SELECT * FROM ci0 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}
do_eqp_test 6.3 {
  SELECT * FROM ci1 WHERE x LIKE ?
} {{SCAN TABLE ci1 VIRTUAL TABLE INDEX 0:}}
} {{SCAN ci1 VIRTUAL TABLE INDEX 0:}}
do_eqp_test 6.4 {
  SELECT * FROM ci1 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}

finish_test

Changes to ext/misc/appendvfs.c.
526
527
528
529
530
531
532
533
534
535





536
537
538
539
540
541
542
526
527
528
529
530
531
532



533
534
535
536
537
538
539
540
541
542
543
544







-
-
-
+
+
+
+
+







  memset(pApndFile, 0, sizeof(ApndFile));
  pFile->pMethods = &apnd_io_methods;
  pApndFile->iMark = -1;    /* Append mark not yet written */

  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
  if( rc==SQLITE_OK ){
    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
  }
  if( rc ){
    pBaseFile->pMethods->xClose(pBaseFile);
    if( rc ){
      pBaseFile->pMethods->xClose(pBaseFile);
    }
  }
  if( rc ){
    pFile->pMethods = 0;
    return rc;
  }
  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
    /* The file being opened appears to be just an ordinary DB. Copy
    ** the base dispatch-table so this instance mimics the base VFS. 
    */
Changes to ext/misc/cksumvfs.c.
575
576
577
578
579
580
581












582
583
584
585
586
587
588
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600







+
+
+
+
+
+
+
+
+
+
+
+







           && sqlite3_stricmp(azArg[1], "page_size")==0 ){
      /* Do not allow page size changes on a checksum database */
      return SQLITE_OK;
    }
  }else if( op==SQLITE_FCNTL_CKPT_START || op==SQLITE_FCNTL_CKPT_DONE ){
    p->inCkpt = op==SQLITE_FCNTL_CKPT_START;
    if( p->pPartner ) p->pPartner->inCkpt = p->inCkpt;
  }else if( op==SQLITE_FCNTL_CKSM_FILE ){
    /* This VFS needs to obtain a pointer to the corresponding database
    ** file handle from within xOpen() calls to open wal files. To do this,
    ** it uses the sqlite3_database_file_object() API to obtain a pointer
    ** to the file-handle used by SQLite to access the db file. This is
    ** fine if cksmvfs happens to be the top-level VFS, but not if there
    ** are one or more wrapper VFS. To handle this case, this file-control
    ** is used to extract the cksmvfs file-handle from any wrapper file 
    ** handle.  */
    sqlite3_file **ppFile = (sqlite3_file**)pArg;
    *ppFile = (sqlite3_file*)p;
    return SQLITE_OK;
  }
  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
    *(char**)pArg = sqlite3_mprintf("cksm/%z", *(char**)pArg);
  }
  return rc;
}
684
685
686
687
688
689
690


691
692
693
694
695
696
697
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711







+
+







  memset(p, 0, sizeof(*p));
  pSubFile = ORIGFILE(pFile);
  pFile->pMethods = &cksm_io_methods;
  rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
  if( rc ) goto cksm_open_done;
  if( flags & SQLITE_OPEN_WAL ){
    sqlite3_file *pDb = sqlite3_database_file_object(zName);
    rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
    assert( rc==SQLITE_OK );
    p->pPartner = (CksmFile*)pDb;
    assert( p->pPartner->pPartner==0 );
    p->pPartner->pPartner = p;
    p->isWal = 1;
    p->computeCksm = p->pPartner->computeCksm;
  }else{
    p->isWal = 0;
Changes to ext/misc/decimal.c.
455
456
457
458
459
460
461
462
463
464
465





466
467
468
469
470
471
472
455
456
457
458
459
460
461




462
463
464
465
466
467
468
469
470
471
472
473







-
-
-
-
+
+
+
+
+







  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==0 ) return;
  pB->sign = !pB->sign;
  decimal_add(pA, pB);
  decimal_result(context, pA);
  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
Changes to ext/misc/json1.c.
295
296
297
298
299
300
301
302

303
304
305
306
307
308
309
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309







-
+







/* 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( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
  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++] = '\\';
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1894
1895
1896
1897
1898
1899
1900

1901
1902
1903
1904
1905
1906
1907
1908
1909







-

+







  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;
    }
    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 ){
1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975

1976
1977






1978
1979
1980
1981
1982
1983
1984
1955
1956
1957
1958
1959
1960
1961

1962




1963
1964
1965
1966
1967
1968
1969
1970
1971
1972


1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985







-
+
-
-
-
-









+
-
-
+
+
+
+
+
+







  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; (c = z[i])!=',' || inStr || nNest; i++){
  for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
    if( i>=pStr->nUsed ){
      pStr->nUsed = 1;
      return;
    }
    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);
    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


/*
Changes to ext/misc/zipfile.c.
32
33
34
35
36
37
38














39
40
41
42


43
44
45
46
47
48
49
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
+
+








#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 unsigned short u16;
typedef unsigned long u32;
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))
702
703
704
705
706
707
708


709
710
711



712
713
714
715
716



717
718
719
720
721
722
723
724



725
726
727
728


729
730
731

732
733
734

735
736


737
738
739
740
741
742
743
716
717
718
719
720
721
722
723
724



725
726
727





728
729
730








731
732
733
734



735
736



737



738


739
740
741
742
743
744
745
746
747







+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+

-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
+
+







**     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;
  int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
  int M = ((pCDS->mDate >> 5) & 0x0F);
  int D = (pCDS->mDate & 0x1F);
  Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
  M = ((pCDS->mDate >> 5) & 0x0F);
  D = (pCDS->mDate & 0x1F);
  int B = -13;

  int sec = (pCDS->mTime & 0x1F)*2;
  int min = (pCDS->mTime >> 5) & 0x3F;
  int hr = (pCDS->mTime >> 11) & 0x1F;
  sec = (pCDS->mTime & 0x1F)*2;
  min = (pCDS->mTime >> 5) & 0x3F;
  hr = (pCDS->mTime >> 11) & 0x1F;
  i64 JD;

  /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */

  /* Calculate the JD in seconds for noon on the day in question */
  if( M<3 ){
    Y = Y-1;
    M = M+12;
  if( M<=2 ){
    Y--;
    M += 12;
  }
  JD = (i64)(24*60*60) * (
      (int)(365.25 * (Y + 4716))
    + (int)(30.6001 * (M + 1))
  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;
    + D + B - 1524
  );

  A = Y/100;
  /* Correct the JD for the time within the day */
  JD += (hr-12) * 3600 + min * 60 + sec;

  B = 2 - A + (A/4);
  /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
  return (u32)(JD - (i64)(24405875) * 24*60*6);
  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.
*/
2166
2167
2168
2169
2170
2171
2172




2173
2174
2175
2176
2177
2178
2179
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187







+
+
+
+







  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
Changes to ext/rbu/rbu1.test.
128
129
130
131
132
133
134





135
136
137
138
139
140
141
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146







+
+
+
+
+







foreach {tn3 create_vfs destroy_vfs} {
  1 {} {}
  2 {
    sqlite3rbu_create_vfs -default myrbu ""
  } {
    sqlite3rbu_destroy_vfs myrbu
  }
  3 {
    sqlite3_register_cksumvfs
  } {
    sqlite3_unregister_cksumvfs
  }
} {

  eval $create_vfs

  foreach {tn2 cmd} {
      1 run_rbu 
      2 step_rbu 3 step_rbu_uri 4 step_rbu_state
Changes to ext/rbu/sqlite3rbu.c.
1616
1617
1618
1619
1620
1621
1622


1623

1624
1625
1626
1627
1628
1629
1630
1616
1617
1618
1619
1620
1621
1622
1623
1624

1625
1626
1627
1628
1629
1630
1631
1632







+
+
-
+







          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;
        if( zQuoted[0]=='N' ){
        }else if( zQuoted[0]=='N' ){
          bFailed = 1;
          break;
        }
        zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
        zSep = ", ";
      }

4988
4989
4990
4991
4992
4993
4994
4995

4996
4997
4998
4999
5000

5001
5002
5003
5004


5005
5006

5007
5008
5009
5010

5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
4990
4991
4992
4993
4994
4995
4996

4997





4998

4999


5000
5001
5002

5003




5004






5005
5006
5007
5008
5009
5010
5011







-
+
-
-
-
-
-
+
-

-
-
+
+

-
+
-
-
-
-
+
-
-
-
-
-
-







      ** 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. This
          /* This call is to open a *-wal file. Intead, open the *-oal. */
          ** code ensures that the string passed to xOpen() is terminated by a
          ** pair of '\0' bytes in case the VFS attempts to extract a URI 
          ** parameter from it.  */
          const char *zBase = zName;
          size_t nCopy;
          size_t nOpen;
          char *zCopy;
          if( rbuIsVacuum(pDb->pRbu) ){
            zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
            zBase = sqlite3_filename_wal(zBase);
            zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
            zOpen = sqlite3_filename_wal(zOpen);
          }
          nCopy = strlen(zBase);
          nOpen = strlen(zOpen);
          zCopy = sqlite3_malloc64(nCopy+2);
          if( zCopy ){
            memcpy(zCopy, zBase, nCopy);
            zCopy[nCopy-3] = 'o';
          ((char*)zOpen)[nOpen-3] = 'o';
            zCopy[nCopy] = '\0';
            zCopy[nCopy+1] = '\0';
            zOpen = (const char*)(pFd->zDel = zCopy);
          }else{
            rc = SQLITE_NOMEM;
          }
          pFd->pRbu = pDb->pRbu;
        }
        pDb->pWalFd = pFd;
      }
    }
  }else{
    pFd->pRbu = pRbuVfs->pRbu;
Changes to ext/rtree/geopoly.c.
306
307
308
309
310
311
312




313
314
315
316
317
318
319
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323







+
+
+
+







  GeoPoly *p = 0;
  int nByte;
  if( sqlite3_value_type(pVal)==SQLITE_BLOB
   && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
  ){
    const unsigned char *a = sqlite3_value_blob(pVal);
    int nVertex;
    if( a==0 ){
      sqlite3_result_error_nomem(pCtx);
      return 0;
    }
    nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
    if( (a[0]==0 || a[0]==1)
     && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
    ){
      p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
      if( p==0 ){
        if( pRc ) *pRc = SQLITE_NOMEM;
679
680
681
682
683
684
685
686

687
688
689
690
691
692
693
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697







-
+







    }else{
      sqlite3_free(p);
      aCoord[0].f = mnX;
      aCoord[1].f = mxX;
      aCoord[2].f = mnY;
      aCoord[3].f = mxY;
    }
  }else{
  }else if( aCoord ){
    memset(aCoord, 0, sizeof(RtreeCoord)*4);
  }
  return pOut;
}

/*
** Implementation of the geopoly_bbox(X) SQL function.
Changes to ext/rtree/rtree.c.
3886
3887
3888
3889
3890
3891
3892

3893
3894
3895
3896

3897




3898
3899
3900
3901
3902
3903
3904
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898

3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909







+




+
-
+
+
+
+







** 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));
      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().
*/
Changes to ext/rtree/rtree6.test.
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
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







-
-
+
+






-
-
+
+






-
-
+
+






-
-
+
+





-
-
+
+






-
-
+
+







  rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
} {C0}

do_eqp_test rtree6.2.1 {
  SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_eqp_test rtree6.2.2 {
  SELECT * FROM t1,t2 WHERE k=ii AND x1<10
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:C0
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_eqp_test rtree6.2.3 {
  SELECT * FROM t1,t2 WHERE k=ii
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_eqp_test rtree6.2.4.1 {
  SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
  `--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
  `--SEARCH t2 USING AUTOMATIC COVERING INDEX (v=?)
}
do_eqp_test rtree6.2.4.2 {
  SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
  `--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1
  `--SEARCH t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
}

do_eqp_test rtree6.2.5 {
  SELECT * FROM t1,t2 WHERE k=ii AND x1<v
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 2:
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_execsql_test rtree6-3.1 {
  CREATE VIRTUAL TABLE t3 USING rtree(id, x1, x2, y1, y2);
  INSERT INTO t3 VALUES(NULL, 1, 1, 2, 2);
  SELECT * FROM t3 WHERE 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
Changes to ext/rtree/rtreeC.test.
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
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







-
-
+
+







-
-
+
+







-
-
+
+






-
-
+
+







}

do_eqp_test 1.1 {
  SELECT * FROM r_tree, t 
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 1.2 {
  SELECT * FROM t, r_tree
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 1.3 {
  SELECT * FROM t, r_tree
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 1.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE t
  |--SCAN r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN t
}

do_execsql_test 2.0 {
  INSERT INTO t VALUES(0, 0);
  INSERT INTO t VALUES(0, 1);
  INSERT INTO t VALUES(0, 2);
  INSERT INTO t VALUES(0, 3);
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
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







-
-
+
+







-
-
+
+







-
-
+
+






-
-
+
+













-
-
+
+



-
-
+
+




-
-
+
+



-
-
+
+







sqlite3 db test.db

do_eqp_test 2.1 {
  SELECT * FROM r_tree, t 
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 2.2 {
  SELECT * FROM t, r_tree
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 2.3 {
  SELECT * FROM t, r_tree
  WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
  QUERY PLAN
  |--SCAN TABLE t
  `--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
  |--SCAN t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 2.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE t
  |--SCAN r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN t
}

#-------------------------------------------------------------------------
# Test that the special CROSS JOIN handling works with rtree tables.
#
do_execsql_test 3.1 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(y);
  CREATE VIRTUAL TABLE t3 USING rtree(z, x1,x2, y1,y2);
}

do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE t2
  |--SCAN t1
  `--SCAN t2
}
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
  QUERY PLAN
  |--SCAN TABLE t2
  `--SCAN TABLE t1
  |--SCAN t2
  `--SCAN t1
}

do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
  |--SCAN t1
  `--SCAN t3 VIRTUAL TABLE INDEX 2:
}
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
  QUERY PLAN
  |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE t1
  |--SCAN t3 VIRTUAL TABLE INDEX 2:
  `--SCAN t1
}

#--------------------------------------------------------------------
# Test that LEFT JOINs are not reordered if the right-hand-side is
# a virtual table.
#
reset_db
199
200
201
202
203
204
205
206
207


208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224


225
226
227
228
229
230
231
232
233
234
235
236
237


238
239
240
241
242
243
244
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222


223
224
225
226
227
228
229
230
231
232
233
234
235


236
237
238
239
240
241
242
243
244







-
-
+
+















-
-
+
+











-
-
+
+







# First test a query with no ANALYZE data at all. The outer loop is
# real table "t1".
#
do_eqp_test 5.2 {
  SELECT * FROM t1, rt WHERE x==id;
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
  |--SCAN t1
  `--SCAN rt VIRTUAL TABLE INDEX 1:
}

# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
# contains very few rows. This causes it to move "rt" to the outer loop.
#
do_execsql_test 5.3 {
  ANALYZE;
  DELETE FROM sqlite_stat1 WHERE tbl='t1';
}
db close
sqlite3 db test.db
do_eqp_test 5.4 {
  SELECT * FROM t1, rt WHERE x==id;
} {
  QUERY PLAN
  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
  `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
  |--SCAN rt VIRTUAL TABLE INDEX 2:
  `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
}

# Delete the ANALYZE data. "t1" should be the outer loop again.
#
do_execsql_test 5.5 { DROP TABLE sqlite_stat1; }
db close
sqlite3 db test.db
do_eqp_test 5.6 {
  SELECT * FROM t1, rt WHERE x==id;
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
  |--SCAN t1
  `--SCAN rt VIRTUAL TABLE INDEX 1:
}

# This time create and attach a database that contains ANALYZE data for
# tables of the same names as those used internally by virtual table
# "rt". Check that the rtree module is not fooled into using this data.
# Table "t1" should remain the outer loop.
#
254
255
256
257
258
259
260
261
262


263
264
265
266
267
268
269
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
269







-
-
+
+







  sqlite3 db test.db
  execsql { ATTACH 'test.db2' AS aux; }
} {}
do_eqp_test 5.8 {
  SELECT * FROM t1, rt WHERE x==id;
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
  |--SCAN t1
  `--SCAN rt VIRTUAL TABLE INDEX 1:
}

#--------------------------------------------------------------------
# Test that having a second connection drop the sqlite_stat1 table
# before it is required by rtreeConnect() does not cause problems.
#
ifcapable rtree {
323
324
325
326
327
328
329
330
331
332



333
334
335
336
337
338
339
340
341
342
343
344
345



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360



361
362
363
364
365
366
367
368
369
370
371
372
373



374
375
376
377
378
323
324
325
326
327
328
329



330
331
332
333
334
335
336
337
338
339
340
341
342



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357



358
359
360
361
362
363
364
365
366
367
368
369
370



371
372
373
374
375
376
377
378







-
-
-
+
+
+










-
-
-
+
+
+












-
-
-
+
+
+










-
-
-
+
+
+






do_eqp_execsql_test 7.1 {
  SELECT id FROM xdir, rt, ydir 
  ON (y1 BETWEEN ymin AND ymax)
  WHERE (x1 BETWEEN xmin AND xmax);
} {
  QUERY PLAN
  |--SCAN TABLE xdir
  |--SCAN TABLE ydir
  `--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
  |--SCAN xdir
  |--SCAN ydir
  `--SCAN rt VIRTUAL TABLE INDEX 2:B2D3B0D1
} {
  2 4
}

do_eqp_execsql_test 7.2 {
  SELECT * FROM xdir, rt LEFT JOIN ydir 
  ON (y1 BETWEEN ymin AND ymax)
  WHERE (x1 BETWEEN xmin AND xmax);
} {
  QUERY PLAN
  |--SCAN TABLE xdir
  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN TABLE ydir
  |--SCAN xdir
  |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN ydir
} {
  5 1 2 7 12 14 {}
  5 2 2 7  8 12 10
  5 4 5 5 10 10 10
}

do_eqp_execsql_test 7.3 {
  SELECT id FROM xdir, rt CROSS JOIN ydir 
  ON (y1 BETWEEN ymin AND ymax)
  WHERE (x1 BETWEEN xmin AND xmax);
} {
  QUERY PLAN
  |--SCAN TABLE xdir
  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN TABLE ydir
  |--SCAN xdir
  |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN ydir
} {
  2 4
}

do_eqp_execsql_test 7.4 {
  SELECT id FROM rt, xdir CROSS JOIN ydir 
  ON (y1 BETWEEN ymin AND ymax)
  WHERE (x1 BETWEEN xmin AND xmax);
} {
  QUERY PLAN
  |--SCAN TABLE xdir
  |--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN TABLE ydir
  |--SCAN xdir
  |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN ydir
} {
  2 4
}

finish_test
Changes to ext/rtree/rtreefuzz001.test.
1041
1042
1043
1044
1045
1046
1047


































































































































































1048
1049
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
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
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


|   2880: ff ff ff 06 00 00 00 0c 00 00 00 01 00 00 00 0b   ................
|   2896: 00 00 00 00 00 00 00 02 40 00 00 00 00 00 00 00   ........@.......
| end crash-2e81f5dce5cbd4.db}]
  execsql { PRAGMA writable_schema = 1;}
  catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}

do_test rtreefuzz001-600 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename crash-7b37d80f000235.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 05   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 10 06 00 00 00 04   ................
|     96: 00 00 00 00 0d 00 00 00 05 0e 49 00 0f 99 0f 40   ..........I....@
|    112: 0e da 0e 8f 0e 49 00 00 00 00 00 00 00 00 00 00   .....I..........
|   3648: 00 00 00 00 00 00 00 00 00 44 05 06 17 15 15 08   .........D......
|   3664: 6f 74 61 62 6c 65 67 65 6f 31 67 65 6f 31 43 52   otablegeo1geo1CR
|   3680: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   3696: 4c 45 20 67 65 6f 31 20 55 53 49 4e 47 20 67 65   LE geo1 USING ge
|   3712: 6f 70 6f 6c 79 28 74 79 70 65 2c 63 6c 72 29 49   opoly(type,clr)I
|   3728: 04 06 17 1f 1f 01 63 74 61 62 6c 65 71 75 65 72   ......ctablequer
|   3744: 79 70 6f 6c 79 71 75 65 72 79 70 6f 6c 79 05 43   ypolyquerypoly.C
|   3760: 52 45 41 54 45 20 54 41 42 4c 45 20 71 75 65 72   REATE TABLE quer
|   3776: 79 70 6f 6c 79 28 70 6f 6c 79 20 4a 53 4f 4e 2c   ypoly(poly JSON,
|   3792: 20 63 6c 72 20 54 45 58 54 29 64 03 07 17 23 23    clr TEXT)d...##
|   3808: 01 81 0f 74 61 62 6c 65 67 65 6f 31 5f 70 61 72   ...tablegeo1_par
|   3824: 65 6e 74 67 65 6f 31 5f 70 61 72 65 6e 74 04 43   entgeo1_parent.C
|   3840: 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65 6f   REATE TABLE .geo
|   3856: 31 5f 70 61 72 65 6e 74 22 28 6e 6f 64 65 6e 6f   1_parent.(nodeno
|   3872: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
|   3888: 20 4b 45 59 2c 70 61 72 65 6e 74 6e 6f 64 85 29    KEY,parentnod.)
|   3904: 57 02 06 17 1f 1f 01 7f 74 61 62 6c 65 67 65 6f   W.......tablegeo
|   3920: 31 5f 6e 6f 64 65 67 65 6f 31 5f 6e 6f 64 65 03   1_nodegeo1_node.
|   3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 22 67 65   CREATE TABLE .ge
|   3952: 6f 31 5f 6e 6f 64 65 22 28 6e 6f 64 65 6e 6f 20   o1_node.(nodeno 
|   3968: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20   INTEGER PRIMARY 
|   3984: 4b 45 59 2c 64 61 74 61 29 65 01 07 17 21 21 01   KEY,data)e...!!.
|   4000: 81 15 74 61 62 6c 65 67 65 6f 31 5f 72 6f 77 69   ..tablegeo1_rowi
|   4016: 64 67 65 6f 31 5f 72 6f 77 69 64 02 43 52 45 41   dgeo1_rowid.CREA
|   4032: 54 45 20 54 41 42 4c 45 20 22 67 65 6f 31 5f 72   TE TABLE .geo1_r
|   4048: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45   owid.(rowid INTE
|   4064: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c   GER PRIMARY KEY,
|   4080: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 2c 61 32 29   nodeno,a0,a1,a2)
| page 2 offset 4096
|      0: 0d 00 00 00 0a 0d ab 00 0f c9 0f 88 0f 48 0f 00   .............H..
|   3488: 00 00 00 00 00 00 00 00 00 00 00 45 82 0a 06 00   ...........E....
|   3504: 09 74 1d 13 01 00 00 06 00 80 b5 43 00 80 ac 43   .t.........C...C
|   3520: 00 00 bd 43 8f 82 9f 43 71 fd c9 43 8f 02 a7 43   ...C...Cq..C...C
|   3536: 71 fd c8 43 e4 bd a8 43 64 bb bd 43 f4 3d a2 43   q..C...Cd..C.=.C
|   3552: 64 3b b7 43 00 80 ad 43 61 6e 67 6c 65 2d 33 30   d;.C...Cangle-30
|   3568: 72 65 64 32 81 4e 06 00 09 44 23 17 01 00 00 03   red2.N...D#.....
|   3584: 00 40 3f 44 00 c0 20 44 00 c0 46 44 00 c0 20 44   .@?D.. D..FD.. D
|   3600: 00 00 43 44 00 40 28 44 74 72 69 61 6e 67 6c 65   ..CD.@(Dtriangle
|   3616: 2d 33 30 62 6c 61 63 6b 35 82 3e 06 00 09 54 1d   -30black5.>...T.
|   3632: 13 01 00 00 04 00 40 54 44 00 80 1d 44 9a c9 5c   ......@TD...D...
|   3648: 44 66 36 1b 44 33 13 5f 44 00 c0 23 44 9a 89 5b   Df6.D3._D..#D..[
|   3664: 44 a4 60 1d 44 61 72 72 6f 77 2d 35 30 72 65 64   D.`.Darrow-50red
|   3680: 36 74 06 00 09 54 1b 17 01 00 00 04 00 80 0d 44   6t...T.........D
|   3696: 00 00 f2 42 0a d7 04 44 00 00 ca 42 0a 77 05 44   ...B...D...B.w.D
|   3712: 0a 57 c1 42 00 20 0e 44 0a 57 e9 42 6c 69 6e 65   .W.B. .D.W.Bline
|   3728: 2d 34 30 67 72 65 65 6e 36 72 06 00 09 54 1b 17   -40green6r...T..
|   3744: 01 00 00 04 00 00 7b 43 00 00 ea 42 29 5c 58 43   .......C...B).XC
|   3760: 00 00 c2 42 29 dc 5a 43 0a 57 b9 42 00 80 7d 43   ...B).ZC.W.B...C
|   3776: 0a 57 e1 42 6c 69 6e 65 2d 34 30 67 72 65 65 6e   .W.Bline-40green
|   3792: 36 54 06 00 09 54 1b 17 01 00 00 04 00 00 a2 43   6T...T.........C
|   3808: 00 00 24 44 00 00 b6 43 00 00 24 44 00 00 b6 43   ..$D...C..$D...C
|   3824: 00 40 25 44 00 00 a2 43 00 40 25 44 6c 69 6e 65   .@%D...C.@%Dline
|   3840: 2d 34 30 62 6c 61 63 6b 3e 37 06 00 09 64 1d 15   -40black>7...d..
|   3856: 01 00 00 05 00 80 f0 43 00 00 54 43 66 16 01 44   .......C..TCf..D
|   3872: 66 a6 30 43 cd ec 09 44 00 00 54 43 8f 0a 09 44   f.0C...D..TC...D
|   3888: a4 d0 73 43 66 16 01 44 9a 59 77 43 68 6f 75 73   ..sCf..D.YwChous
|   3904: 65 2d 37 30 62 6c 75 65 3e 35 06 00 09 64 1d 15   e-70blue>5...d..
|   3920: 01 00 00 05 00 00 a2 43 00 00 5a 43 cd ac b3 43   .......C..ZC...C
|   3936: 66 a6 36 43 9a 59 c5 43 00 00 5a 43 1f 95 c3 43   f.6C.Y.C..ZC...C
|   3952: a4 d0 79 43 cd ac b3 43 9a 59 7d 43 68 6f 75 73   ..yC...C.Y.Chous
|   3968: 65 2d 37 30 62 6c 75 65 3f 2c 06 00 09 64 1d 17   e-70blue?,...d..
|   3984: 01 00 00 05 00 00 f5 43 00 00 2f 43 00 00 07 44   .......C../C...D
|   4000: 00 00 2f 43 00 00 07 44 00 00 61 43 00 c0 00 44   ../C...D..aC...D
|   4016: 00 00 75 43 00 00 f5 43 00 00 61 43 68 6f 75 73   ..uC...C..aChous
|   4032: 65 2d 37 30 62 6c 61 63 6b 35 1f 06 10 09 54 19   e-70black5....T.
|   4048: 17 01 00 00 04 00 00 9b 43 00 00 67 43 0a 57 92   ........C..gC.W.
|   4064: 43 00 00 5d 43 0a 57 97 43 14 ae 4b 42 ff ff a0   C..]C.W.C..KB...
|   4080: 43 14 ae 55 43 62 6f 78 2d 32 30 67 72 65 65 6e   C..UCbox-20green
| page 3 offset 8192
|      0: 0d 00 00 00 01 0b 2d 00 0b 2e 00 00 00 00 00 00   ......-.........
|   2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50   ...............P
|   2864: 01 04 00 93 24 00 00 00 0a 00 00 00 00 00 00 01   ....$...........
|   2880: 0a 43 b5 80 00 43 c9 fd 71 43 9f 82 8f 43 ad 80   .C...C..qC...C..
|   2896: 00 00 00 00 00 00 00 00 72 43 58 5c 29 43 7d 80   ........rCX.)C..
|   2912: 00 42 b9 57 0a 42 ea 00 00 00 00 00 00 00 00 00   .B.W.B..........
|   2928: 35 43 a2 00 00 43 c5 59 9a 43 36 a6 66 43 7d 59   5C...C.Y.C6.fC.Y
|   2944: 9a 00 00 00 00 00 00 00 1f 43 92 57 0a 43 a0 00   .........C.W.C..
|   2960: 00 43 4b ae 14 43 67 00 00 00 00 00 00 00 00 00   .CK..Cg.........
|   2976: 37 43 f0 80 00 44 09 ec cd 43 30 a6 66 43 77 59   7C...D...C0.fCwY
|   2992: 9a 00 00 00 00 00 00 00 2c 43 f5 00 00 44 07 00   ........,C...D..
|   3008: 00 43 2f 00 00 43 75 00 00 00 00 00 00 00 00 00   .C/..Cu.........
|   3024: 74 44 04 d7 0a 44 0e 20 00 42 c1 57 0a 42 f2 00   tD...D. .B.W.B..
|   3040: 00 00 00 00 00 00 00 00 ce 44 3f 40 00 44 46 c0   .........D?@.DF.
|   3056: 00 44 20 c0 00 44 28 40 00 00 00 00 00 00 00 00   .D ..D(@........
|   3072: be 44 54 40 00 44 5f 13 33 44 1b 36 66 44 23 c0   .DT@.D_.3D.6fD#.
|   3088: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3104: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00   .D$..D%@........
|   3120: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40   TC...C...D$..D%@
|   3136: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3152: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00   .D$..D%@........
|   3168: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40   TC...C...D$..D%@
|   3184: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3200: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00   .D$..D%@........
|   3216: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40   TC...C...D$..D%@
|   3232: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3248: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00   .D$..D%@........
|   3264: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40   TC...C...D$..D%@
|   3280: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3296: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 00   .D$..D%@........
|   3312: 54 43 a2 00 00 43 b6 00 00 44 24 00 00 44 25 40   TC...C...D$..D%@
|   3328: 00 00 00 00 00 00 00 00 54 43 a2 00 00 43 b6 00   ........TC...C..
|   3344: 00 44 24 00 00 44 25 40 00 00 00 00 00 00 00 01   .D$..D%@........
|   3360: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3376: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3392: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3408: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3424: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3440: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3456: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3472: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3488: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3504: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3520: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3536: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3552: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3568: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3584: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3600: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3616: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3632: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3648: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
|   3664: 00 00 00 00 00 00 00 01 36 44 53 e0 00 44 56 bb   ........6DS..DV.
|   3680: 64 43 71 34 bc 43 7d 00 00 00 00 00 00 00 00 01   dCq4.C..........
|   3696: 36 44 53 e0 00 44 56 bb 64 43 71 34 bc 43 7d 00   6DS..DV.dCq4.C..
| page 4 offset 12288
|      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
| page 5 offset 16384
|      0: 0d 00 00 00 01 0f 8f 00 00 00 00 00 00 00 00 00   ................
|   3968: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f   ...............o
|   3984: 01 04 81 57 19 5b 5b 33 30 30 2c 33 30 30 5d 2c   ...W.[[300,300],
|   4000: 5b 34 30 30 2c 33 35 30 5d 2c 5b 35 30 30 2c 32   [400,350],[500,2
|   4016: 35 30 5d 2c 5b 34 38 30 2c 35 30 30 5d 2c 5b 34   50],[480,500],[4
|   4032: 30 30 2c 34 38 30 5d 2c 5c 33 30 30 2c 35 35 30   00,480],.300,550
|   4048: 5d 2c 5b 32 38 30 2c 34 35 30 5d 2c 5b 33 32 30   ],[280,450],[320
|   4064: 2c 34 30 30 5d 2c 5b 32 38 30 2c 33 35 30 5d 2c   ,400],[280,350],
|   4080: 5b 33 30 30 2c 33 30 00 00 00 00 00 00 00 00 00   [300,30.........
| end crash-7b37d80f000235.db
}]} {}

ifcapable geopoly {

do_catchsql_test rtreefuzz001-601 {
  SAVEPOINT one;
  UPDATE geo1 SET clr=CASE WHEN rowid IN ( SELECT geo1.rowid FROM geo1, querypoly ) THEN 'e' ELSE 'blue' END;
} {1 {database disk image is malformed}}

do_catchsql_test rtreefuzz001-602 {
  SELECT geopoly_svg(_shape, printf('j',geo1.clr)) 
    FROM geo1, querypoly WHERE geopoly_overlap(_shape, poly);
} {1 {database disk image is malformed}}

} ;# ifcapable geopoly

finish_test
Added ext/session/sessionsize.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 April 22
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
} 
source [file join [file dirname [info script]] session_common.tcl]
source $testdir/tester.tcl
ifcapable !session {finish_test; return}

set testprefix sessionsize

proc do_changeset_size_test {tn sql} {
  sqlite3session S db main
  S attach *
  db eval $sql

  set sz [S changeset_size]
  set C [S changeset]
  set szC [string length $C]
  S delete

  do_test $tn "expr $sz" $szC
}

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
  INSERT INTO t1 VALUES(1, 'abc', 'def');
  INSERT INTO t1 VALUES(2, 'ghi', 'jkl');
}

do_changeset_size_test 1.1 {
  INSERT INTO t1 VALUES(3, 'hello', 'world');
}

do_changeset_size_test 1.2 {
  DELETE FROM t1 WHERE a=2;
}

do_changeset_size_test 1.3 {
  DELETE FROM t1 WHERE a=3;
  INSERT INTO t1 VALUES(3, 1, 2);
}

do_changeset_size_test 1.4 {
  UPDATE t1 SET c='hello world' WHERE a=3;
}

#-------------------------------------------------------------------------

do_execsql_test 2.0 {
  CREATE TABlE t2(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
  CREATE TABlE t3(a, b, c, d PRIMARY KEY);
}

do_changeset_size_test 2.1 {
  WITH s(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
  )
  INSERT INTO t2 SELECT i, i+1, i+2, i+3 FROM s;

  UPDATE t2 SET c=randomblob(a) WHERE a>10
}

do_changeset_size_test 2.2 {
  DELETE FROM t2 WHERE a=1;
  INSERT INTO t2 VALUES(1, 4, 3, 4);
}

do_changeset_size_test 2.2 {
  UPDATE t2 SET b=4 WHERE a=2
}

do_changeset_size_test 2.3 {
  INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
  UPDATE t2 SET c='qwertyuiop' WHERE a='a';
}

do_changeset_size_test 2.4 {
  DELETE FROM t2 WHERE a='a';
  INSERT INTO t2 VALUES('a', 'b', 'c', 'd');
}

do_changeset_size_test 2.5 {
  UPDATE t2 SET a='aa', b='bb' WHERE (a, b) = ('a', 'b');
}

do_changeset_size_test 2.6 {
  UPDATE t2 SET a='a', b='b' WHERE (a, b) = ('aa', 'bb');
}

do_changeset_size_test 2.7 {
  INSERT INTO t3 DEFAULT VALUES;
  INSERT INTO t3 VALUES(1,2,3,4);
}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 3.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
}

do_test 3.1 {
  sqlite3session S db main
  S object_config_size -1
} 1

do_test 3.2.1 { S object_config_size 0  } 0
do_test 3.2.2 { S object_config_size -1 } 0
do_test 3.2.3 { S object_config_size 1  } 1
do_test 3.2.4 { S object_config_size -1 } 1

do_test 3.3 { S attach t1 } {}
do_test 3.4 { S object_config_size 1  } {SQLITE_MISUSE}
do_test 3.4 { S object_config_size -1 } {1}

S delete

finish_test

Changes to ext/session/sqlite3session.c.
38
39
40
41
42
43
44

45
46
47
48
49
50
51

52
53
54
55
56
57
58
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60







+







+








/*
** 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 */
};

/*
287
288
289
290
291
292
293
294
295



296
297
298
299
300
301
302
289
290
291
292
293
294
295


296
297
298
299
300
301
302
303
304
305







-
-
+
+
+







*/

/*
** For each row modified during a session, there exists a single instance of
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
  int op;                         /* One of UPDATE, DELETE, INSERT */
  int bIndirect;                  /* True if this change is "indirect" */
  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 
1117
1118
1119
1120
1121
1122
1123






1124
1125
1126
1127
1128
1129
1130
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139







+
+
+
+
+
+







          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
1162
1163
1164
1165
1166
1167
1168

































































































1169
1170
1171
1172
1173
1174
1175
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
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  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
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354







-







      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). */
      SessionChange *pChange; /* New change object */
      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 */
1261
1262
1263
1264
1265
1266
1267
1268
1269


1270
1271
1272
1273
1274


1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289

1290
1291
1292
1293
1294

1295
1296
1297
1298
1299




1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310







1311
1312
1313
1314
1315
1316
1317
1366
1367
1368
1369
1370
1371
1372


1373
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
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414

1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428







-
-
+
+



-
-
+
+














-
+




-
+

-
-
-
-
+
+
+
+










-
+
+
+
+
+
+
+







        /* 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 */
      pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
      if( !pChange ){
      pC = (SessionChange *)sessionMalloc64(pSession, nByte);
      if( !pC ){
        rc = SQLITE_NOMEM;
        goto error_out;
      }else{
        memset(pChange, 0, sizeof(SessionChange));
        pChange->aRecord = (u8 *)&pChange[1];
        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(&pChange->aRecord[nByte], p, &nByte);
        sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
      }

      /* Add the change to the hash-table */
      if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
        pChange->bIndirect = 1;
        pC->bIndirect = 1;
      }
      pChange->nRecord = nByte;
      pChange->op = op;
      pChange->pNext = pTab->apChange[iHash];
      pTab->apChange[iHash] = pChange;
      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 ){
2516
2517
2518
2519
2520
2521
2522
2523





2524
2525
2526
2527
2528
2529
2530
2627
2628
2629
2630
2631
2632
2633

2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645







-
+
+
+
+
+







** using sqlite3_free().
*/
int sqlite3session_changeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
  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().
*/
int sqlite3session_changeset_strm(
  sqlite3_session *pSession,
2607
2608
2609
2610
2611
2612
2613

































2614
2615
2616
2617
2618
2619
2620
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








/*
** Return the amount of heap memory in use.
*/
sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
  return pSession->nMalloc;
}

/*
** Configure the session object passed as the first argument.
*/
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.
*/
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),
Changes to ext/session/sqlite3session.h.
75
76
77
78
79
80
81
































82
83
84
85
86
87
88
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**
** 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.
*/
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.
*/
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
319
320
321
322
323
324
325
















326
327
328
329
330
331
332
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







*/
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.
*/
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 ext/session/test_session.c.
242
243
244
245
246
247
248


249
250
251
252
253
254
255
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257







+
+







    { "enable",       1, "BOOL",       }, /* 3 */
    { "indirect",     1, "BOOL",       }, /* 4 */
    { "isempty",      0, "",           }, /* 5 */
    { "table_filter", 1, "SCRIPT",     }, /* 6 */
    { "patchset",     0, "",           }, /* 7 */
    { "diff",         2, "FROMDB TBL", }, /* 8 */
    { "memory_used",  0, "",           }, /* 9 */
    { "changeset_size", 0, "",         }, /* 10 */
    { "object_config_size", 1, "INTEGER", }, /* 11 */
    { 0 }
  };
  int iSub;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
353
354
355
356
357
358
359























360
361
362
363
364
365
366
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    }

    case 9: {      /* memory_used */
      sqlite3_int64 nMalloc = sqlite3session_memory_used(pSession);
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nMalloc));
      break;
    }

    case 10: {
      sqlite3_int64 nSize = sqlite3session_changeset_size(pSession);
      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize));
      break;
    }
    case 11: {
      int rc;
      int iArg;
      if( Tcl_GetIntFromObj(interp, objv[2], &iArg) ){
        return TCL_ERROR;
      }
      rc = sqlite3session_object_config(
          pSession, SQLITE_SESSION_OBJCONFIG_SIZE, &iArg
      );
      if( rc!=SQLITE_OK ){
        extern const char *sqlite3ErrName(int);
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
      }else{
        Tcl_SetObjResult(interp, Tcl_NewIntObj(iArg));
      }
      break;
    }
  }

  return TCL_OK;
}

static void SQLITE_TCLAPI test_session_del(void *clientData){
  TestSession *p = (TestSession*)clientData;
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
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







+




















+
+
+
+
+
+
+







  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  Tcl_CmdInfo info;
  int rc;                         /* sqlite3session_create() return code */
  TestSession *p;                 /* New wrapper object */
  int iArg = -1;

  if( objc!=4 ){
    Tcl_WrongNumArgs(interp, 1, objv, "CMD DB-HANDLE DB-NAME");
    return TCL_ERROR;
  }

  if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[2]), &info) ){
    Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(objv[2]), 0);
    return TCL_ERROR;
  }
  db = *(sqlite3 **)info.objClientData;

  p = (TestSession*)ckalloc(sizeof(TestSession));
  memset(p, 0, sizeof(TestSession));
  rc = sqlite3session_create(db, Tcl_GetString(objv[3]), &p->pSession);
  if( rc!=SQLITE_OK ){
    ckfree((char*)p);
    return test_session_error(interp, rc, 0);
  }

  /* Query the SQLITE_SESSION_OBJCONFIG_SIZE option to ensure that it
  ** is clear by default. Then set it. */
  sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);
  assert( iArg==0 );
  iArg = 1;
  sqlite3session_object_config(p->pSession,SQLITE_SESSION_OBJCONFIG_SIZE,&iArg);

  Tcl_CreateObjCommand(
      interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p,
      test_session_del
  );
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}
Changes to main.mk.
437
438
439
440
441
442
443
444


445
446
447
448
449
450
451
437
438
439
440
441
442
443

444
445
446
447
448
449
450
451
452







-
+
+







  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/misc/stmt.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/session/test_session.c
  $(TOP)/ext/session/test_session.c \
  fts5.c

# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \
Changes to src/alter.c.
25
26
27
28
29
30
31
32

33

34
35
36
37
38
39
40
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40
41







-
+

+







** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
** If the table is a system table, this function leaves an error message
** 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) 
  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;
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
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







-
+







-
+

-
+








-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** objects unusable.
*/
static void renameTestSchema(
  Parse *pParse,                  /* Parse context */
  const char *zDb,                /* Name of db to verify schema of */
  int bTemp,                      /* True if this is the temp db */
  const char *zWhen,              /* "when" part of error message */
  const char *zDropColumn         /* Name of column being dropped */
  int bNoDQS                      /* Do not allow DQS in the schema */
){
  pParse->colNamesSet = 1;
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\"." DFLT_SCHEMA_TABLE " "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      " AND sql NOT LIKE 'create virtual%%'"
      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %Q)=NULL ",
      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
      zDb,
      zDb, bTemp, zWhen, zDropColumn
      zDb, bTemp, zWhen, bNoDQS
  );

  if( bTemp==0 ){
    sqlite3NestedParse(pParse, 
        "SELECT 1 "
        "FROM temp." DFLT_SCHEMA_TABLE " "
        "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
        " AND sql NOT LIKE 'create virtual%%'"
        " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %Q)=NULL ",
        zDb, zWhen, zDropColumn
        " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
        zDb, zWhen, bNoDQS
    );
  }
}

/*
** Generate VM code to replace any double-quoted strings (but not double-quoted
** identifiers) within the "sql" column of the sqlite_schema table in 
** database zDb with their single-quoted equivalents. If argument bTemp is
** not true, similarly update all SQL statements in the sqlite_schema table
** of the temp db.
*/
static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\"." DFLT_SCHEMA_TABLE 
      " SET sql = sqlite_rename_quotefix(%Q, sql)"
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
  );
  if( bTemp==0 ){
    sqlite3NestedParse(pParse, 
      "UPDATE temp." DFLT_SCHEMA_TABLE
      " SET sql = sqlite_rename_quotefix('temp', sql)"
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      " AND sql NOT LIKE 'create virtual%%'"
    );
  }
}

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
233
234
235
236
237
238
239
240

241
242
243
244
245
246
247
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_schema SET "
            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
            "tbl_name = "
              "CASE WHEN tbl_name=%Q COLLATE nocase AND "
              "  sqlite_rename_test(%Q, sql, type, name, 1, 'after rename',0) "
              "  sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
              "THEN %Q ELSE tbl_name END "
            "WHERE type IN ('view', 'trigger')"
        , zDb, zTabName, zName, zTabName, zDb, zName);
  }

  /* If this is a virtual table, invoke the xRename() function if
  ** one is defined. The xRename() callback will modify the names
591
592
593
594
595
596
597




598
599
600
601
602
603
604
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633







+
+
+
+







  for(iCol=0; iCol<pTab->nCol; iCol++){
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
  }
  if( iCol==pTab->nCol ){
    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
    goto exit_rename_column;
  }

  /* Ensure the schema contains no double-quoted strings */
  renameTestSchema(pParse, zDb, iSchema==1, "", 0);
  renameFixQuotes(pParse, zDb, iSchema==1);

  /* Do the rename operation using a recursive UPDATE statement that
  ** uses the sqlite_rename_column() SQL function to compute the new
  ** CREATE statement text for the sqlite_schema table.
  */
  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
621
622
623
624
625
626
627
628

629
630
631
632
633
634
635
650
651
652
653
654
655
656

657
658
659
660
661
662
663
664







-
+







      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
      "WHERE type IN ('trigger', 'view')",
      zDb, pTab->zName, iCol, zNew, bQuote
  );

  /* Drop and reload the database schema. */
  renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
  renameTestSchema(pParse, zDb, iSchema==1, "after rename", 0);
  renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
831
832
833
834
835
836
837

838
839
840
841
842
843
844
845







-
+







/*
** 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( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
  if( p->selFlags & SF_View ) return WRC_Prune;
  if( ALWAYS(p->pEList) ){
    ExprList *pList = p->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
        sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
      }
    }
886
887
888
889
890
891
892
893



894
895
896
897
898
899
900
915
916
917
918
919
920
921

922
923
924
925
926
927
928
929
930
931







-
+
+
+







*/
static RenameToken *renameTokenFind(
  Parse *pParse, 
  struct RenameCtx *pCtx, 
  void *pPtr
){
  RenameToken **pp;
  assert( pPtr!=0 );
  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;
1045
1046
1047
1048
1049
1050
1051
1052

1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1076
1077
1078
1079
1080
1081
1082

1083

1084
1085
1086
1087
1088




1089
1090
1091
1092
1093
1094
1095







-
+
-





-
-
-
-







** is initialized by this function before it is used.
*/
static int renameParseSql(
  Parse *p,                       /* Memory to use for Parse object */
  const char *zDb,                /* Name of schema SQL belongs to */
  sqlite3 *db,                    /* Database handle */
  const char *zSql,               /* SQL to parse */
  int bTemp,                      /* True if SQL is from temp schema */
  int bTemp                       /* True if SQL is from temp schema */
  const char *zDropColumn         /* Name of column being dropped */
){
  int rc;
  char *zErr = 0;

  db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
  if( zDropColumn ){
    db->init.bDropColumn = 1;
    db->init.azInit = (char**)&zDropColumn;
  }

  /* Parse the SQL statement passed as the first argument. If no error
  ** occurs and the parse does not result in a new table, index or
  ** trigger object, the database must be corrupt. */
  memset(p, 0, sizeof(Parse));
  p->eParseMode = PARSE_MODE_RENAME;
  p->db = db;
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127







-







    for(pToken=p->pRename; pToken; pToken=pToken->pNext){
      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
    }
  }
#endif

  db->init.iDb = 0;
  db->init.bDropColumn = 0;
  return rc;
}

/*
** This function edits SQL statement zSql, replacing each token identified
** by the linked list pRename with the text of zNew. If argument bQuote is
** true, then zNew is always quoted first. If no error occurs, the result
1112
1113
1114
1115
1116
1117
1118
1119

1120
1121



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
1151
1152
1153



1154
1155
1156
1157
1158
1159























1160
1161
1162
1163
1164
1165
1166
1137
1138
1139
1140
1141
1142
1143

1144
1145

1146
1147
1148
1149
1150














1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
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







-
+

-
+
+
+

+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
-
+
+
-
-





-
-


+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  const char *zNew,               /* New token text */
  int bQuote                      /* True to always quote token */
){
  int nNew = sqlite3Strlen30(zNew);
  int nSql = sqlite3Strlen30(zSql);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  int rc = SQLITE_OK;
  char *zQuot;
  char *zQuot = 0;
  char *zOut;
  int nQuot;
  int nQuot = 0;
  char *zBuf1 = 0;
  char *zBuf2 = 0;

  if( zNew ){
  /* Set zQuot to point to a buffer containing a quoted copy of the 
  ** identifier zNew. If the corresponding identifier in the original 
  ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
  ** point to zQuot so that all substitutions are made using the
  ** quoted version of the new column name.  */
  zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
  if( zQuot==0 ){
    return SQLITE_NOMEM;
  }else{
    nQuot = sqlite3Strlen30(zQuot);
  }
  if( bQuote ){
    zNew = zQuot;
    nNew = nQuot;
    /* Set zQuot to point to a buffer containing a quoted copy of the 
    ** identifier zNew. If the corresponding identifier in the original 
    ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
    ** point to zQuot so that all substitutions are made using the
    ** quoted version of the new column name.  */
    zQuot = sqlite3MPrintf(db, "\"%w\" ", zNew);
    if( zQuot==0 ){
      return SQLITE_NOMEM;
    }else{
      nQuot = sqlite3Strlen30(zQuot)-1;
    }

    assert( nQuot>=nNew );
    zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
  }else{
    zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
    if( zOut ){
      zBuf1 = &zOut[nSql*2+1];
      zBuf2 = &zOut[nSql*4+2];
    }
  }

  /* At this point pRename->pList contains a list of RenameToken objects
  ** corresponding to all tokens in the input SQL that must be replaced
  ** with the new column name. All that remains is to construct and
  ** return the edited SQL string. */
  ** with the new column name, or with single-quoted versions of themselves. 
  ** All that remains is to construct and return the edited SQL string. */
  assert( nQuot>=nNew );
  zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
  if( zOut ){
    int nOut = nSql;
    memcpy(zOut, zSql, nSql);
    while( pRename->pList ){
      int iOff;                   /* Offset of token to replace in zOut */
      RenameToken *pBest = renameColumnTokenNext(pRename);

      u32 nReplace;
      const char *zReplace;
      RenameToken *pBest = renameColumnTokenNext(pRename);

      if( zNew ){
      if( sqlite3IsIdChar(*pBest->t.z) ){
        nReplace = nNew;
        zReplace = zNew;
      }else{
        nReplace = nQuot;
        zReplace = zQuot;
        if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
          nReplace = nNew;
          zReplace = zNew;
        }else{
          nReplace = nQuot;
          zReplace = zQuot;
          if( pBest->t.z[pBest->t.n]=='"' ) nReplace++;
        }
      }else{
        /* Dequote the double-quoted token. Then requote it again, this time
        ** using single quotes. If the character immediately following the
        ** original token within the input SQL was a single quote ('), then
        ** add another space after the new, single-quoted version of the
        ** token. This is so that (SELECT "string"'alias') maps to
        ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias').  */
        memcpy(zBuf1, pBest->t.z, pBest->t.n);
        zBuf1[pBest->t.n] = 0;
        sqlite3Dequote(zBuf1);
        sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
            pBest->t.z[pBest->t.n]=='\'' ? " " : ""
        );
        zReplace = zBuf2;
        nReplace = sqlite3Strlen30(zReplace);
      }

      iOff = pBest->t.z - zSql;
      if( pBest->t.n!=nReplace ){
        memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 
            nOut - (iOff + pBest->t.n)
        );
1390
1391
1392
1393
1394
1395
1396
1397

1398
1399
1400
1401
1402
1403
1404
1440
1441
1442
1443
1444
1445
1446

1447
1448
1449
1450
1451
1452
1453
1454







-
+







  zOld = pTab->aCol[iCol].zName;
  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);

#ifndef SQLITE_OMIT_AUTHORIZATION
  db->xAuth = 0;
#endif
  rc = renameParseSql(&sParse, zDb, db, zSql, bTemp, 0);
  rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);

  /* Find tokens that need to be replaced. */
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = &sParse;
  sWalker.xExprCallback = renameColumnExprCb;
  sWalker.xSelectCallback = renameColumnSelectCb;
  sWalker.u.pRename = &sCtx;
1524
1525
1526
1527
1528
1529
1530
1531

1532
1533
1534
1535
1536
1537
1538
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
1588







-
+







** Walker select callback used by "RENAME TABLE". 
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
  int i;
  RenameCtx *p = pWalker->u.pRename;
  SrcList *pSrc = pSelect->pSrc;
  if( pSelect->selFlags & SF_View ) return WRC_Prune;
  if( pSrc==0 ){
  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);
1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1644
1645
1646
1647
1648
1649
1650

1651
1652
1653
1654
1655
1656
1657
1658







-
+







    sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
    memset(&sWalker, 0, sizeof(Walker));
    sWalker.pParse = &sParse;
    sWalker.xExprCallback = renameTableExprCb;
    sWalker.xSelectCallback = renameTableSelectCb;
    sWalker.u.pRename = &sCtx;

    rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, 0);
    rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);

    if( rc==SQLITE_OK ){
      int isLegacy = (db->flags & SQLITE_LegacyAlter);
      if( sParse.pNewTable ){
        Table *pTab = sParse.pNewTable;

        if( pTab->pSelect ){
1696
1697
1698
1699
1700
1701
1702

















































































































1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717

1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736

1737
1738
1739
1740
1741
1742
1743

1744
1745
1746


1747


1748
1749
1750
1751
1752
1753
1754
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879

1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898

1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912

1913
1914
1915
1916
1917
1918
1919
1920
1921







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+














-
+


















-
+







+



+
+
-
+
+







#ifndef SQLITE_OMIT_AUTHORIZATION
    db->xAuth = xAuth;
#endif
  }

  return;
}

static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
    renameTokenFind(pWalker->pParse, pWalker->u.pRename, (void*)pExpr);
  }
  return WRC_Continue;
}

/*
** The implementation of an SQL scalar function that rewrites DDL statements
** so that any string literals that use double-quotes are modified so that
** they use single quotes.
**
** Two arguments must be passed:
**
**   0: Database name ("main", "temp" etc.).
**   1: SQL statement to edit.
**
** The returned value is the modified SQL statement. For example, given
** the database schema:
**
**   CREATE TABLE t1(a, b, c);
**
**   SELECT sqlite_rename_quotefix('main', 
**       'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
**   );
**
** returns the string:
** 
**   CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
*/
static void renameQuotefixFunc(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  char const *zDb = (const char*)sqlite3_value_text(argv[0]);
  char const *zInput = (const char*)sqlite3_value_text(argv[1]);

#ifndef SQLITE_OMIT_AUTHORIZATION
  sqlite3_xauth xAuth = db->xAuth;
  db->xAuth = 0;
#endif

  sqlite3BtreeEnterAll(db);

  UNUSED_PARAMETER(NotUsed);
  if( zDb && zInput ){
    int rc;
    Parse sParse;
    rc = renameParseSql(&sParse, zDb, db, zInput, 0);

    if( rc==SQLITE_OK ){
      RenameCtx sCtx;
      Walker sWalker;

      /* Walker to find tokens that need to be replaced. */
      memset(&sCtx, 0, sizeof(RenameCtx));
      memset(&sWalker, 0, sizeof(Walker));
      sWalker.pParse = &sParse;
      sWalker.xExprCallback = renameQuotefixExprCb;
      sWalker.xSelectCallback = renameColumnSelectCb;
      sWalker.u.pRename = &sCtx;

      if( sParse.pNewTable ){
        Select *pSelect = sParse.pNewTable->pSelect;
        if( pSelect ){
          pSelect->selFlags &= ~SF_View;
          sParse.rc = SQLITE_OK;
          sqlite3SelectPrep(&sParse, pSelect, 0);
          rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
          if( rc==SQLITE_OK ){
            sqlite3WalkSelect(&sWalker, pSelect);
          }
        }else{
          int i;
          sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
          for(i=0; i<sParse.pNewTable->nCol; i++){
            sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
          }
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
        }
      }else if( sParse.pNewIndex ){
        sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
        sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
      }else{
#ifndef SQLITE_OMIT_TRIGGER
        rc = renameResolveTrigger(&sParse);
        if( rc==SQLITE_OK ){
          renameWalkTrigger(&sWalker, sParse.pNewTrigger);
        }
#endif /* SQLITE_OMIT_TRIGGER */
      }

      if( rc==SQLITE_OK ){ 
        rc = renameEditSql(context, &sCtx, zInput, 0, 0);
      }
      renameTokenFree(db, sCtx.pList);
    }
    if( rc!=SQLITE_OK ){
      sqlite3_result_error_code(context, rc);
    }
    renameParseCleanup(&sParse);
  }

#ifndef SQLITE_OMIT_AUTHORIZATION
  db->xAuth = xAuth;
#endif

  sqlite3BtreeLeaveAll(db);
}

/*
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
** reloaded, this function is called on each SQL statement in the schema
** to ensure that it is still usable.
**
**   0: Database name ("main", "temp" etc.).
**   1: SQL statement.
**   2: Object type ("view", "table", "trigger" or "index").
**   3: Object name.
**   4: True if object is from temp schema.
**   5: "when" part of error message.
**   6: Name of column being dropped, or NULL.
**   6: True to disable the DQS quirk when parsing SQL.
**
** Unless it finds an error, this function normally returns NULL. However, it
** returns integer value 1 if:
**
**   * the SQL argument creates a trigger, and
**   * the table that the trigger is attached to is in database zDb.
*/
static void renameTableTest(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  char const *zDb = (const char*)sqlite3_value_text(argv[0]);
  char const *zInput = (const char*)sqlite3_value_text(argv[1]);
  int bTemp = sqlite3_value_int(argv[4]);
  int isLegacy = (db->flags & SQLITE_LegacyAlter);
  char const *zWhen = (const char*)sqlite3_value_text(argv[5]);
  char const *zDropColumn = (const char*)sqlite3_value_text(argv[6]);
  int bNoDQS = sqlite3_value_int(argv[6]);

#ifndef SQLITE_OMIT_AUTHORIZATION
  sqlite3_xauth xAuth = db->xAuth;
  db->xAuth = 0;
#endif

  UNUSED_PARAMETER(NotUsed);

  if( zDb && zInput ){
    int rc;
    Parse sParse;
    int flags = db->flags;
    if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
    rc = renameParseSql(&sParse, zDb, db, zInput, bTemp, zDropColumn);
    rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
    db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
    if( rc==SQLITE_OK ){
      if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
        NameContext sNC;
        memset(&sNC, 0, sizeof(sNC));
        sNC.pParse = &sParse;
        sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
        if( sParse.nErr ) rc = sParse.rc;
1808
1809
1810
1811
1812
1813
1814
1815

1816
1817
1818
1819
1820
1821
1822
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1989







-
+








#ifndef SQLITE_OMIT_AUTHORIZATION
  sqlite3_xauth xAuth = db->xAuth;
  db->xAuth = 0;
#endif

  UNUSED_PARAMETER(NotUsed);
  rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1, 0);
  rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
  if( rc!=SQLITE_OK ) goto drop_column_done;
  pTab = sParse.pNewTable;
  if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){ 
    /* This can happen if the sqlite_schema table is corrupt */
    rc = SQLITE_CORRUPT_BKPT;
    goto drop_column_done;
  }
1902
1903
1904
1905
1906
1907
1908

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936

1937
1938



1939




1940
1941
1942
1943
1944
1945

1946
1947
1948
1949



1950


1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979

1980
1981
1982
1983
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085

2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108
2109

2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127

2128
2129
2130
2131
2132

2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163







+









-
+















-


+


+
+
+
-
+
+
+
+






+




+
+
+
-
+
+



-






+



















+




  }

  /* Edit the sqlite_schema table */
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
  zDb = db->aDb[iDb].zDbSName;
  renameTestSchema(pParse, zDb, iDb==1, "", 0);
  renameFixQuotes(pParse, zDb, iDb==1);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
      "sql = sqlite_drop_column(%d, sql, %d) "
      "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
      , zDb, iDb, iCol, pTab->zName
  );

  /* Drop and reload the database schema. */
  renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
  renameTestSchema(pParse, zDb, iDb==1, "after drop column", zCol);
  renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);

  /* Edit rows of table on disk */
  if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
    int i;
    int addr;
    int reg;
    int regRec;
    Index *pPk = 0;
    int nField = 0;               /* Number of non-virtual columns after drop */
    int iCur;
    Vdbe *v = sqlite3GetVdbe(pParse);
    iCur = pParse->nTab++;
    sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
    addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
    reg = ++pParse->nMem;
    pParse->nMem += pTab->nCol;
    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
      pParse->nMem += pTab->nCol;
    }else{
      pPk = sqlite3PrimaryKeyIndex(pTab);
      pParse->nMem += pPk->nColumn;
      for(i=0; i<pPk->nKeyCol; i++){
        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
    }
      }
      nField = pPk->nKeyCol;
    }
    regRec = ++pParse->nMem;
    for(i=0; i<pTab->nCol; i++){
      if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
        int regOut;
        if( pPk ){
          int iPos = sqlite3TableColumnToIndex(pPk, i);
          int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
          if( iPos<pPk->nKeyCol ) continue;
          regOut = reg+1+iPos-(iPos>iColPos);
        }else{
          regOut = reg+1+nField;
        }
        if( i==pTab->iPKey ){
          sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
        }else{
        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
        }
        nField++;
      }
    }
    regRec = reg + pTab->nCol;
    sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
    if( pPk ){
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
    }else{
      sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
    }
    sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);

    sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addr);
  }

exit_drop_column:
  sqlite3DbFree(db, zCol);
  sqlite3SrcListDelete(db, pSrc);
}

/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
  static FuncDef aAlterTableFuncs[] = {
    INTERNAL_FUNCTION(sqlite_rename_column,  9, renameColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_table,   7, renameTableFunc),
    INTERNAL_FUNCTION(sqlite_rename_test,    7, renameTableTest),
    INTERNAL_FUNCTION(sqlite_drop_column,    3, dropColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
  };
  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif  /* SQLITE_ALTER_TABLE */
Changes to src/attach.c.
508
509
510
511
512
513
514
515

516
517
518
519
520
521
522
508
509
510
511
512
513
514

515
516
517
518
519
520
521
522







-
+







  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 = 0;
  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
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584










585
586
587
588
589
590
591
592
593
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







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+









     || sqlite3WalkExpr(&pFix->w, pStep->pWhere) 
     || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
     || sqlite3FixSrcList(pFix, pStep->pFrom)
    ){
      return 1;
    }
#ifndef SQLITE_OMIT_UPSERT
    if( pStep->pUpsert ){
      Upsert *pUp = pStep->pUpsert;
      if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
       || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
       || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
       || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
      ){
        return 1;
    {
      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;
}
#endif
Changes to src/btree.c.
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458







+







  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;
1485
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523

1524
1525
1526

1527
1528
1529

1530
1531
1532
1533
1534
1535
1536
1537
1538

1539
1540
1541
1542
1543
1544
1545
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521

1522
1523
1524

1525
1526
1527

1528
1529
1530

1531
1532
1533
1534
1535

1536
1537


1538
1539
1540
1541
1542
1543
1544
1545







-
+


















+









-
+


-
+


-
+


-
+




-


-
-
+







        }
        if( iFree2 ){
          if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
          sz2 = get2byte(&data[iFree2+2]);
          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
          sz += sz2;
        }else if( NEVER(iFree+sz>usableSize) ){
        }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<iCellFirst || pc>iCellLast ){
    if( pc<iCellStart || pc>iCellLast ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( pc>=iCellFirst && pc<=iCellLast );
    assert( pc>=iCellStart && pc<=iCellLast );
    size = pPage->xCellSize(pPage, &src[pc]);
    cbrk -= size;
    if( cbrk<iCellFirst || pc+size>usableSize ){
    if( cbrk<iCellStart || pc+size>usableSize ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
    assert( cbrk+size<=usableSize && cbrk>=iCellStart );
    testcase( cbrk+size==usableSize );
    testcase( pc+size==usableSize );
    put2byte(pAddr, cbrk);
    if( temp==0 ){
      int x;
      if( cbrk==pc ) continue;
      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
      x = get2byte(&data[hdr+5]);
      memcpy(&temp[x], &data[x], (cbrk+size) - x);
      memcpy(&temp[iCellStart], &data[iCellStart], (cbrk+size) - iCellStart);
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:
5390
5391
5392
5393
5394
5395
5396
5397



5398
5399
5400
5401
5402
5403
5404
5390
5391
5392
5393
5394
5395
5396

5397
5398
5399
5400
5401
5402
5403
5404
5405
5406







-
+
+
+







#ifdef SQLITE_DEBUG
    /* This block serves to assert() that the cursor really does point 
    ** to the last entry in the b-tree. */
    int ii;
    for(ii=0; ii<pCur->iPage; ii++){
      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
    }
    assert( pCur->ix==pCur->pPage->nCell-1 );
    assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
    testcase( pCur->ix!=pCur->pPage->nCell-1 );
    /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
    assert( pCur->pPage->leaf );
#endif
    *pRes = 0;
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);
6157
6158
6159
6160
6161
6162
6163
6164

6165
6166
6167
6168
6169
6170
6171
6159
6160
6161
6162
6163
6164
6165

6166
6167
6168
6169
6170
6171
6172
6173







-
+







          }
        }else{
          closest = 0;
        }

        iPage = get4byte(&aData[8+closest*4]);
        testcase( iPage==mxPage );
        if( iPage>mxPage ){
        if( iPage>mxPage || iPage<2 ){
          rc = SQLITE_CORRUPT_PGNO(iTrunk);
          goto end_allocate_page;
        }
        testcase( iPage==mxPage );
        if( !searchList 
         || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) 
        ){
7009
7010
7011
7012
7013
7014
7015
7016

7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029

7030
7031
7032
7033
7034
7035
7036
7037
7038
7011
7012
7013
7014
7015
7016
7017

7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030

7031
7032

7033
7034
7035
7036
7037
7038
7039







-
+












-
+

-







  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,pEnd) ){
    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;
    memcpy(pData, pCell, sz);
    memmove(pData, pCell, sz);
    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
    testcase( sz!=pPg->xCellSize(pPg,pCell) )
    i++;
    if( i>=iEnd ) break;
    if( pCArray->ixNx[k]<=i ){
      k++;
      pSrcEnd = pCArray->apEnd[k];
    }
  }
7163
7164
7165
7166
7167
7168
7169
7170



7171
7172
7173
7174
7175
7176
7177
7164
7165
7166
7167
7168
7169
7170

7171
7172
7173
7174
7175
7176
7177
7178
7179
7180







-
+
+
+







      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;
        if( NEVER(pFree+sz>pEnd) ){
          return 0;  /* Corruption - should be previously detected */
        }
      }else{
        pFree = pCell;
        szFree += sz;
      }
      nRet++;
    }
  }
7816
7817
7818
7819
7820
7821
7822
7823

7824
7825
7826
7827
7828
7829
7830
7819
7820
7821
7822
7823
7824
7825

7826
7827
7828
7829
7830
7831
7832
7833







-
+







      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 );
        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
8139
8140
8141
8142
8143
8144
8145

8146
8147
8148
8149
8150
8151
8152
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156







+







  }

  /* 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;
8182
8183
8184
8185
8186
8187
8188






8189
8190
8191
8192
8193
8194
8195
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205







+
+
+
+
+
+







        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
8724
8725
8726
8727
8728
8729
8730








8731
8732
8733
8734
8735
8736
8737
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755







+
+
+
+
+
+
+
+







  ** 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 */
    invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828

8829
8830
8831
8832
8833
8834
8835
8829
8830
8831
8832
8833
8834
8835

8836
8837
8838
8839
8840
8841
8842
8843
8844

8845
8846
8847
8848
8849
8850
8851
8852







-









-
+







        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( pCur->eState>CURSOR_INVALID ){
    if( NEVER(pCur->eState>CURSOR_INVALID) ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      rc = btreeComputeFreeSpace(pPage);
    }
    if( rc ) return rc;
  }

9102
9103
9104
9105
9106
9107
9108

9109

9110
9111

9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126

9127
9128

9129
9130
9131
9132
9133
9134
9135
9136







+
-
+

-
+







  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 ) return rc;
    if( rc || pCur->eState!=CURSOR_VALID ) return rc;
  }
  assert( pCur->eState==CURSOR_VALID );
  assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );

  iCellDepth = pCur->iPage;
  iCellIdx = pCur->ix;
  pPage = pCur->pPage;
  pCell = findCell(pPage, iCellIdx);
  if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;

Changes to src/build.c.
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464







-
+








  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 ){
    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 ){
        if( IsSharedSchema(db) && pParse->nErr==0 ){
          int bDummy = 0;
483
484
485
486
487
488
489


490
491
492
493
494
495
496
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498







+
+







  if( p==0 && (!IsSharedSchema(db) || pParse->nErr==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( p==0 || HasRowid(p) || p->iPKey<0 );
  }

  return p;
}

/*
** Locate the table identified by *p.
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
1197
1198
1199
1200
1201
1202
1203











1204
1205
1206
1207
1208
1209
1210







-
-
-
-
-
-
-
-
-
-
-







  pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
#else
  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#endif
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,
  ** then record a pointer to this table in the main database structure
  ** so that INSERT can find the table easily.
  */
#ifndef SQLITE_OMIT_AUTOINCREMENT
  if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    pTable->pSchema->pSeqTab = pTable;
  }
#endif

  /* Begin generating the code that will insert the table record into
  ** the schema table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359







+







  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)
2212
2213
2214
2215
2216
2217
2218
2219




2220
2221
2222
2223
2224
2225
2226
2227
2228




2229
2230
2231
2232
2233
2234
2235
2204
2205
2206
2207
2208
2209
2210

2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222

2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233







-
+
+
+
+








-
+
+
+
+







  */
  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 ) return;
    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 ) return;
    if( db->mallocFailed || pParse->nErr ){
      pTab->tabFlags &= ~TF_WithoutRowid;
      return;
    }
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk->nKeyCol==1 );
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );

    /*
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436







-







  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;
  }
  assert( !db->mallocFailed );
  p = pParse->pNewTable;
  if( p==0 ) return;

  if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
    p->tabFlags |= TF_Shadow;
  }

2650
2651
2652
2653
2654
2655
2656
2657

2658
2659
2660
2661
2662
2663
2664
2647
2648
2649
2650
2651
2652
2653

2654
2655
2656
2657
2658
2659
2660
2661







-
+







    sqlite3DbFree(db, zStmt);
    sqlite3ChangeCookie(pParse, iDb);

#ifndef SQLITE_OMIT_AUTOINCREMENT
    /* Check to see if we need to create an sqlite_sequence table for
    ** keeping track of autoincrement keys.
    */
    if( (p->tabFlags & TF_Autoincrement)!=0 ){
    if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){
      Db *pDb = &db->aDb[iDb];
      assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
      if( pDb->pSchema->pSeqTab==0 ){
        sqlite3NestedParse(pParse,
          "CREATE TABLE %Q.sqlite_sequence(name,seq)",
          pDb->zDbSName
        );
2673
2674
2675
2676
2677
2678
2679

2680
2681
2682
2683
2684
2685
2686
2687











2688
2689
2690
2691
2692
2693
2694
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703







+








+
+
+
+
+
+
+
+
+
+
+








  /* Add the table to the in-memory representation of the database.
  */
  if( db->init.busy ){
    Table *pOld;
    Schema *pSchema = p->pSchema;
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    assert( HasRowid(p) || p->iPKey<0 );
    pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      sqlite3OomFault(db);
      return;
    }
    pParse->pNewTable = 0;
    db->mDbFlags |= DBFLAG_SchemaChange;

    /* If this is the magic sqlite_sequence table used by autoincrement,
    ** then record a pointer to this table in the main database structure
    ** so that INSERT can find the table easily.  */
    assert( !pParse->nested );
#ifndef SQLITE_OMIT_AUTOINCREMENT
    if( strcmp(p->zName, "sqlite_sequence")==0 ){
      assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
      p->pSchema->pSeqTab = p;
    }
#endif
  }

#ifndef SQLITE_OMIT_ALTERTABLE
  if( !pSelect && !p->pSelect ){
    assert( pCons && pEnd );
    if( pCons->z==0 ){
      pCons = pEnd;
2724
2725
2726
2727
2728
2729
2730










2731
2732
2733
2734
2735
2736
2737
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756







+
+
+
+
+
+
+
+
+
+







  if( pParse->nVar>0 ){
    sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
    goto create_view_fail;
  }
  sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
  p = pParse->pNewTable;
  if( p==0 || pParse->nErr ) goto create_view_fail;

  /* Legacy versions of SQLite allowed the use of the magic "rowid" column
  ** on a view, even though views do not have rowids.  The following flag
  ** setting fixes this problem.  But the fix can be disabled by compiling
  ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
  ** depend upon the old buggy behavior. */
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
  p->tabFlags |= TF_NoVisibleRowid;
#endif

  sqlite3TwoPartName(pParse, pName1, pName2, &pName);
  iDb = sqlite3SchemaToIndex(db, p->pSchema);
  sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
  if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
4251
4252
4253
4254
4255
4256
4257
4258

4259
4260
4261
4262
4263
4264
4265
4270
4271
4272
4273
4274
4275
4276

4277
4278
4279
4280
4281
4282
4283
4284







-
+







  ** 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) );
  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) );
4286
4287
4288
4289
4290
4291
4292
4293

4294
4295
4296
4297
4298
4299
4300
4305
4306
4307
4308
4309
4310
4311

4312
4313
4314
4315
4316
4317
4318
4319







-
+







  assert( pName->nSrc==1 );
  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
    goto exit_drop_index;
  }
  pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
  if( pIndex==0 ){
    if( !ifExists ){
      sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
      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 ){
4601
4602
4603
4604
4605
4606
4607
4608
4609


4610
4611
4612
4613
4614
4615
4616
4620
4621
4622
4623
4624
4625
4626


4627
4628
4629
4630
4631
4632
4633
4634
4635







-
-
+
+








/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
  int i;
  SrcItem *pItem;
  assert(pList || pParse->db->mallocFailed );
  if( pList ){
  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);
      }
    }
Changes to src/expr.c.
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
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







+
+
+
+







-






-
-
-







    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);
  }
  if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    return sqlite3AffinityType(pExpr->u.zToken, 0);
  }
#endif
  if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
    return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
  }
  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 ){
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
91
92
93
94
95
96
97












98
99
100
101
102
103
104
105







-
-
-
-
-
-
-
-
-
-
-
-
+







*/
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 */
){
  assert( pExpr!=0 || pParse->db->mallocFailed );
  if( pExpr==0 ) return 0;
  if( pExpr->op==TK_VECTOR ){
    ExprList *pList = pExpr->x.pList;
    if( ALWAYS(pList!=0) ){
      int i;
      for(i=0; i<pList->nExpr; i++){
        pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
                                                       pCollName, dequote);
      }
    }
  }else if( pCollName->n>0 ){
  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;
    }
  }
607
608
609
610
611
612
613

614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635



636
637
638
639

640
641
642
643
644

645
646

647

648
649
650
651
652
653
654
655










656
657
658
659
660
661
662
663

664
665
666
667

668
669
670
671
672
673
674

675



676
677
678
679
680
681
682
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662




663

664
665

666




667
668
669
670
671
672
673
674
675
676
677
678
679
680
681







+



















-
-
-
+
+
+




+





+


+
-
+








+
+
+
+
+
+
+
+
+
+




-
-
-
-
+
-


-
+
-
-
-
-



+

+
+
+







  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int i;
  int regLeft = 0;
  int regRight = 0;
  u8 opx = op;
  int addrCmp = 0;
  int addrDone = sqlite3VdbeMakeLabel(pParse);
  int isCommuted = ExprHasProperty(pExpr,EP_Commuted);

  assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
  if( pParse->nErr ) return;
  if( nLeft!=sqlite3ExprVectorSize(pRight) ){
    sqlite3ErrorMsg(pParse, "row value misused");
    return;
  }
  assert( pExpr->op==TK_EQ || pExpr->op==TK_NE 
       || pExpr->op==TK_IS || pExpr->op==TK_ISNOT 
       || pExpr->op==TK_LT || pExpr->op==TK_GT 
       || pExpr->op==TK_LE || pExpr->op==TK_GE 
  );
  assert( pExpr->op==op || (pExpr->op==TK_IS && op==TK_EQ)
            || (pExpr->op==TK_ISNOT && op==TK_NE) );
  assert( p5==0 || pExpr->op!=op );
  assert( p5==SQLITE_NULLEQ || pExpr->op==op );

  p5 |= SQLITE_STOREP2;
  if( opx==TK_LE ) opx = TK_LT;
  if( opx==TK_GE ) opx = TK_GT;
  if( op==TK_LE ) opx = TK_LT;
  if( op==TK_GE ) opx = TK_GT;
  if( op==TK_NE ) opx = TK_EQ;

  regLeft = exprCodeSubselect(pParse, pLeft);
  regRight = exprCodeSubselect(pParse, pRight);

  sqlite3VdbeAddOp2(v, OP_Integer, 1, dest);
  for(i=0; 1 /*Loop exits by "break"*/; i++){
    int regFree1 = 0, regFree2 = 0;
    Expr *pL, *pR; 
    int r1, r2;
    assert( i>=0 && i<nLeft );
    if( addrCmp ) sqlite3VdbeJumpHere(v, addrCmp);
    r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
    r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
    addrCmp = sqlite3VdbeCurrentAddr(v);
    codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted);
    codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted);
    testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
    testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
    testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
    testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
    testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
    testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
    sqlite3ReleaseTempReg(pParse, regFree1);
    sqlite3ReleaseTempReg(pParse, regFree2);
    if( (opx==TK_LT || opx==TK_GT) && i<nLeft-1 ){
      addrCmp = sqlite3VdbeAddOp0(v, OP_ElseEq);
      testcase(opx==TK_LT); VdbeCoverageIf(v,opx==TK_LT);
      testcase(opx==TK_GT); VdbeCoverageIf(v,opx==TK_GT);
    }
    if( p5==SQLITE_NULLEQ ){
      sqlite3VdbeAddOp2(v, OP_Integer, 0, dest);
    }else{
      sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, dest, r2);
    }
    if( i==nLeft-1 ){
      break;
    }
    if( opx==TK_EQ ){
      sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
      p5 |= SQLITE_KEEPNULL;
    }else if( opx==TK_NE ){
      sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
      sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v);
      p5 |= SQLITE_KEEPNULL;
    }else{
      assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
      sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
      VdbeCoverageIf(v, op==TK_LT);
      VdbeCoverageIf(v, op==TK_GT);
      VdbeCoverageIf(v, op==TK_LE);
      VdbeCoverageIf(v, op==TK_GE);
      if( i==nLeft-2 ) opx = op;
    }
  }
  sqlite3VdbeJumpHere(v, addrCmp);
  sqlite3VdbeResolveLabel(v, addrDone);
  if( op==TK_NE ){
    sqlite3VdbeAddOp2(v, OP_Not, dest, dest);
  }
}

#if SQLITE_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
954
955
956
957
958
959
960
961
962


963
964
965
966
967
968
969
953
954
955
956
957
958
959


960
961
962
963
964
965
966
967
968







-
-
+
+







  if( pLeft==0  ){
    return pRight;
  }else if( pRight==0 ){
    return pLeft;
  }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) 
         && !IN_RENAME_OBJECT
  ){
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
    sqlite3ExprDeferredDelete(pParse, pLeft);
    sqlite3ExprDeferredDelete(pParse, pRight);
    return sqlite3Expr(db, TK_INTEGER, "0");
  }else{
    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
  }
}

/*
1152
1153
1154
1155
1156
1157
1158
















1159
1160
1161
1162
1163
1164
1165
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    sqlite3DbFreeNN(db, p);
  }
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
  if( p ) sqlite3ExprDeleteNN(db, p);
}


/*
** Arrange to cause pExpr to be deleted when the pParse is deleted.
** This is similar to sqlite3ExprDelete() except that the delete is
** deferred untilthe pParse is deleted.
**
** The pExpr might be deleted immediately on an OOM error.
**
** The deferred delete is (currently) implemented by adding the
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
  pParse->pConstExpr = 
      sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}

/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
  if( p ){
    if( IN_RENAME_OBJECT ){
      sqlite3RenameExprUnmap(pParse, p);
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323







+







  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 ){
1372
1373
1374
1375
1376
1377
1378
1379


1380
1381
1382
1383
1384
1385
1386
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
1402
1403







-
+
+







        *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 );
          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);
      }
    }
  }
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505







+







  int i;
  Expr *pPriorSelectCol = 0;
  assert( db!=0 );
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;
  pNew->nAlloc = p->nAlloc;
  pItem = pNew->a;
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
    Expr *pNewExpr;
    pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
    if( pOldExpr 
1616
1617
1618
1619
1620
1621
1622








1623
1624
1625
1626
1627
1628
1629
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655







+
+
+
+
+
+
+
+







    pNew->pWith = withDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
    pNew->pWin = 0;
    pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
    if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
    pNew->selId = p->selId;
    if( db->mallocFailed ){
      /* Any prior OOM might have left the Select object incomplete.
      ** Delete the whole thing rather than allow an incomplete Select
      ** to be used by the code generator. */
      pNew->pNext = 0;
      sqlite3SelectDelete(db, pNew);
      break;
    }
    *pp = pNew;
    pp = &pNew->pPrior;
    pNext = pNew;
  }

  return pRet;
}
1646
1647
1648
1649
1650
1651
1652

1653
1654


1655
1656
1657
1658
1659
1660


1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674













































1675
1676
1677
1678
1679

1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1672
1673
1674
1675
1676
1677
1678
1679


1680
1681

1682
1683
1684


1685
1686














1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733



1734
1735
1736






1737
1738
1739
1740
1741
1742
1743







+
-
-
+
+
-



-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


-
-
-
+


-
-
-
-
-
-







** is a power of two.  That is true for sqlite3ExprListAppend() returns
** but is not necessarily true from the return value of sqlite3ExprListDup().
**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned.  If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
static const struct ExprList_item zeroItem = {0};
ExprList *sqlite3ExprListAppend(
  Parse *pParse,          /* Parsing context */
SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
  sqlite3 *db,            /* Database handle.  Used for memory allocation */
  ExprList *pList,        /* List to which to append. Might be NULL */
  Expr *pExpr             /* Expression to be appended. Might be NULL */
){
  struct ExprList_item *pItem;
  sqlite3 *db = pParse->db;
  assert( db!=0 );
  ExprList *pList;

  if( pList==0 ){
    pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
    if( pList==0 ){
      goto no_mem;
    }
    pList->nExpr = 0;
  }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
    ExprList *pNew;
    pNew = sqlite3DbRealloc(db, pList, 
         sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0]));
    if( pNew==0 ){
      goto no_mem;
    }
    pList = pNew;
  pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
  if( pList==0 ){
    sqlite3ExprDelete(db, pExpr);
    return 0;
  }
  pList->nAlloc = 4;
  pList->nExpr = 1;
  pItem = &pList->a[0];
  *pItem = zeroItem;
  pItem->pExpr = pExpr;
  return pList;
}
SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
  sqlite3 *db,            /* Database handle.  Used for memory allocation */
  ExprList *pList,        /* List to which to append. Might be NULL */
  Expr *pExpr             /* Expression to be appended. Might be NULL */
){
  struct ExprList_item *pItem;
  ExprList *pNew;
  pList->nAlloc *= 2;
  pNew = sqlite3DbRealloc(db, pList, 
       sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
  if( pNew==0 ){
    sqlite3ExprListDelete(db, pList);
    sqlite3ExprDelete(db, pExpr);
    return 0;
  }else{
    pList = pNew;
  }
  pItem = &pList->a[pList->nExpr++];
  *pItem = zeroItem;
  pItem->pExpr = pExpr;
  return pList;
}
ExprList *sqlite3ExprListAppend(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to append. Might be NULL */
  Expr *pExpr             /* Expression to be appended. Might be NULL */
){
  struct ExprList_item *pItem;
  if( pList==0 ){
    return sqlite3ExprListAppendNew(pParse->db,pExpr);
  }
  if( pList->nAlloc<pList->nExpr+1 ){
    return sqlite3ExprListAppendGrow(pParse->db,pList,pExpr);
  }
  pItem = &pList->a[pList->nExpr++];
  assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
  assert( offsetof(struct ExprList_item,pExpr)==0 );
  memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
  *pItem = zeroItem;
  pItem->pExpr = pExpr;
  return pList;

no_mem:     
  /* Avoid leaking memory if malloc has failed. */
  sqlite3ExprDelete(db, pExpr);
  sqlite3ExprListDelete(db, pList);
  return 0;
}

/*
** pColumns and pExpr form a vector assignment which is part of the SET
** clause of an UPDATE statement.  Like this:
**
**        (a,b,c) = (expr1,expr2,expr3)
2293
2294
2295
2296
2297
2298
2299

2300
2301

2302
2303
2304
2305
2306
2307
2308
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359







+


+







** 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.
*/
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:
3144
3145
3146
3147
3148
3149
3150
3151

3152
3153
3154
3155
3156
3157
3158
3195
3196
3197
3198
3199
3200
3201

3202
3203
3204
3205
3206
3207
3208
3209







-
+







** 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.
*/
int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
  int nVector = sqlite3ExprVectorSize(pIn->pLeft);
  if( (pIn->flags & EP_xIsSelect) ){
  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;
3335
3336
3337
3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400







+







    destStep2 = destIfFalse;
  }else{
    destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
  }
  if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
  for(i=0; i<nVector; i++){
    Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
    if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
    if( sqlite3ExprCanBeNull(p) ){
      sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
      VdbeCoverage(v);
    }
  }

  /* Step 3.  The LHS is now known to be non-NULL.  Do the binary search
3960
3961
3962
3963
3964
3965
3966
3967

3968
3969
3970
3971
3972
3973
3974
4012
4013
4014
4015
4016
4017
4018

4019
4020
4021
4022
4023
4024
4025
4026







-
+







      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 );
      assert( op==TK_NULL || pParse->db->mallocFailed );
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      return target;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
4026
4027
4028
4029
4030
4031
4032

4033

4034

4035
4036
4037
4038
4039
4040
4041





4042
4043
4044
4045
4046
4047
4048
4078
4079
4080
4081
4082
4083
4084
4085

4086

4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106







+
-
+
-
+







+
+
+
+
+







    case TK_EQ: {
      Expr *pLeft = pExpr->pLeft;
      if( sqlite3ExprIsVector(pLeft) ){
        codeVectorCompare(pParse, pExpr, target, op, p5);
      }else{
        r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
        r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
        sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
        codeCompare(pParse, pLeft, pExpr->pRight, op,
        codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
            r1, r2, inReg, SQLITE_STOREP2 | p5,
            sqlite3VdbeCurrentAddr(v)+2, p5,
            ExprHasProperty(pExpr,EP_Commuted));
        assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
        assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
        assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
        assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
        assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
        assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
        if( p5==SQLITE_NULLEQ ){
          sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
        }else{
          sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
        }
        testcase( regFree1==0 );
        testcase( regFree2==0 );
      }
      break;
    }
    case TK_AND:
    case TK_OR:
5777
5778
5779
5780
5781
5782
5783
5784
5785

5786
5787
5788
5789
5790
5791
5792
5793
5794
5795

5796
5797
5798
5799
5800
5801
5802
5835
5836
5837
5838
5839
5840
5841


5842
5843
5844
5845
5846
5847
5848
5849
5850


5851
5852
5853
5854
5855
5856
5857
5858







-
-
+








-
-
+







    assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
    if( pExpr->op==TK_AGG_COLUMN ){
      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aCol[iAgg].pCExpr = pExpr;
          pParse->pConstExpr = 
             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }else{
      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aFunc[iAgg].pFExpr = pExpr;
          pParse->pConstExpr = 
             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }
  }
  return WRC_Continue;
}

Changes to src/func.c.
2067
2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
2082
2083
2067
2068
2069
2070
2071
2072
2073

2074


2075
2076
2077
2078
2079
2080
2081







-
+
-
-







  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 2-argument SQL math functions:
** Implementation of 0-argument pi() function.
**
**   power(X,Y)  - Compute X to the Y-th power
*/
static void piFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );
Changes to src/global.c.
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
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







-
+



















+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+







    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
    252,253,254,255
    252,253,254,255,
#endif
#ifdef SQLITE_EBCDIC
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
     96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
    112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
    128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
    160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
    176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
    192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
    224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
    240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
/* All of the upper-to-lower conversion data is above.  The following
** 18 integers are completely unrelated.  They are appended to the
** sqlite3UpperToLower[] array to avoid UBSAN warnings.  Here's what is
** going on:
**
** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
** by invoking sqlite3MemCompare(A,B) which compares values A and B and
** returns negative, zero, or positive if A is less then, equal to, or
** greater than B, respectively.  Then the true false results is found by
** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or 
** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
** is negative, zero, or positive, where opcode is the specific opcode.
** The only works because the comparison opcodes are consecutive and in
** this order: NE EQ GT LE LT GE.  Various assert()s throughout the code
** ensure that is the case.
**
** These elements must be appended to another array.  Otherwise the
** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
** be undefined behavior.  That's goofy, but the C-standards people thought
** it was a good idea, so here we are.
*/
/* NE  EQ  GT  LE  LT  GE  */
   1,  0,  0,  1,  1,  0,  /* aLTb[]: Use when compare(A,B) less than zero */
   0,  1,  0,  1,  0,  1,  /* aEQb[]: Use when compare(A,B) equals zero */
   1,  0,  1,  0,  0,  1   /* aGTb[]: Use when compare(A,B) greater than zero*/
};
const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];

/*
** The following 256 byte lookup table is used to support SQLites built-in
** equivalents to the following standard library functions:
**
**   isspace()                        0x01
**   isalpha()                        0x02
Changes to src/insert.c.
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
354
355
356
357
358
359
360

361
362
363
364
365
366
367
368







-
+







    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)
     || IsVirtual(pSeqTab)
     || NEVER(IsVirtual(pSeqTab))
     || pSeqTab->nCol!=2
    ){
      pParse->nErr++;
      pParse->rc = SQLITE_CORRUPT_SEQUENCE;
      return 0;
    }

813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827







-
+







      }
      if( j>=pTab->nCol ){
        if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
          ipkColumn = i;
          bIdListInOrder = 0;
        }else{
          sqlite3ErrorMsg(pParse, "table %S has no column named %s",
              pTabList, 0, pColumn->a[i].zName);
              pTabList->a, pColumn->a[i].zName);
          pParse->checkSchema = 1;
          goto insert_cleanup;
        }
      }
    }
  }

941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955







-
+







      for(i=0; i<pTab->nCol; i++){
        if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
      }
    }
    if( nColumn!=(pTab->nCol-nHidden) ){
      sqlite3ErrorMsg(pParse, 
         "table %S has %d columns but %d values were supplied",
         pTabList, 0, pTab->nCol-nHidden, nColumn);
         pTabList->a, pTab->nCol-nHidden, nColumn);
     goto insert_cleanup;
    }
  }
  if( pColumn!=0 && nColumn!=pColumn->nId ){
    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
    goto insert_cleanup;
  }
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270







1271
1272
1273
1274
1275
1276
1277
1244
1245
1246
1247
1248
1249
1250

1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284







-
+



















+
+
+
+
+
+
+







      sqlite3VtabMakeWritable(pParse, pTab);
      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
      sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
      sqlite3MayAbort(pParse);
    }else
#endif
    {
      int isReplace;    /* Set to true if constraints may cause a replace */
      int isReplace = 0;/* Set to true if constraints may cause a replace */
      int bUseSeek;     /* True to use OPFLAG_SEEKRESULT */
      sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
          regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
      );
      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);

      /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
      ** constraints or (b) there are no triggers and this table is not a
      ** parent table in a foreign key constraint. It is safe to set the
      ** flag in the second case as if any REPLACE constraint is hit, an
      ** OP_Delete or OP_IdxDelete instruction will be executed on each 
      ** cursor that is disturbed. And these instructions both clear the
      ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
      ** functionality.  */
      bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
      sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
          regIns, aRegIdx, 0, appendFlag, bUseSeek
      );
    }
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
  }else if( pParse->bReturning ){
    /* If there is a RETURNING clause, populate the rowid register with
    ** constant value -1, in case one or more of the returned expressions
    ** refer to the "rowid" of the view.  */
    sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
#endif
  }

  /* Update the count of rows that are inserted
  */
  if( regRowCount ){
    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
  }
Changes to src/main.c.
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1281
1282
1283
1284
1285
1286
1287

1288
1289
1290
1291
1292
1293
1294
1295







-
+







  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 option if there are unfinalized prepared
** 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.
*/
int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
Changes to src/memdb.c.
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180







-
+







  }
  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_NOMEM;
  if( pNew==0 ) return SQLITE_IOERR_NOMEM;
  p->aData = pNew;
  p->szAlloc = newSz;
  return SQLITE_OK;
}

/*
** Write data to an memdb-file.
Changes to src/os.c.
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239







-
+







  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  DO_OS_MALLOC_TEST(0);
  assert( dirSync==0 || dirSync==1 );
  return pVfs->xDelete(pVfs, zPath, dirSync);
  return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
int sqlite3OsAccess(
  sqlite3_vfs *pVfs,
  const char *zPath,
  int flags,
  int *pResOut
){
Changes to src/os_unix.c.
3947
3948
3949
3950
3951
3952
3953

3954
3955
3956
3957
3958
3959
3960
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961







+







  }else{
    pFile->ctrlFlags |= mask;
  }
}

/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
static int unixFcntlExternalReader(unixFile*, int*);

/*
** Information and control of an open file handle.
*/
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  unixFile *pFile = (unixFile*)id;
  switch( op ){
4063
4064
4065
4066
4067
4068
4069




4070
4071
4072
4073
4074
4075
4076
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081







+
+
+
+







#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
      return proxyFileControl(id,op,pArg);
    }
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */

    case SQLITE_FCNTL_EXTERNAL_READER: {
      return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
    }
  }
  return SQLITE_NOTFOUND;
}

/*
** If pFd->sectorSize is non-zero when this function is called, it is a
** no-op. Otherwise, the values of pFd->sectorSize and 
4307
4308
4309
4310
4311
4312
4313


































4314
4315
4316
4317
4318
4319
4320
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







};

/*
** Constants used for locking
*/
#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */

/*
** Use F_GETLK to check whether or not there are any readers with open
** wal-mode transactions in other processes on database file pFile. If
** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are 
** such transactions, or 0 otherwise. If an error occurs, return an
** SQLite error code. The final value of *piOut is undefined in this
** case.
*/
static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
  int rc = SQLITE_OK;
  *piOut = 0;
  if( pFile->pShm){
    unixShmNode *pShmNode = pFile->pShm->pShmNode;
    struct flock f;

    memset(&f, 0, sizeof(f));
    f.l_type = F_WRLCK;
    f.l_whence = SEEK_SET;
    f.l_start = UNIX_SHM_BASE + 3;
    f.l_len = SQLITE_SHM_NLOCK - 3;

    sqlite3_mutex_enter(pShmNode->pShmMutex);
    if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
      rc = SQLITE_IOERR_LOCK;
    }else{
      *piOut = (f.l_type!=F_UNLCK);
    }
    sqlite3_mutex_leave(pShmNode->pShmMutex);
  }

  return rc;
}


/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
** otherwise.
*/
Changes to src/pager.c.
3932
3933
3934
3935
3936
3937
3938
3939


3940
3941
3942
3943
3944
3945
3946
3932
3933
3934
3935
3936
3937
3938

3939
3940
3941
3942
3943
3944
3945
3946
3947







-
+
+







**
** This function is only called right before committing a transaction.
** Once this function has been called, the transaction must either be
** rolled back or committed. It is not safe to call this function and
** then continue writing to the database.
*/
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
  assert( pPager->dbSize>=nPage );
  assert( pPager->dbSize>=nPage || CORRUPT_DB );
  testcase( pPager->dbSize<nPage );
  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
  pPager->dbSize = nPage;

  /* At one point the code here called assertTruncateConstraint() to
  ** ensure that all pages being truncated away by this operation are,
  ** if one or more savepoints are open, present in the savepoint 
  ** journal so that they can be restored if the savepoint is rolled
5832
5833
5834
5835
5836
5837
5838
5839

5840
5841
5842
5843
5844
5845
5846
5833
5834
5835
5836
5837
5838
5839

5840
5841
5842
5843
5844
5845
5846
5847







-
+







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( ALWAYS(pPager->eState==PAGER_READER) ){
  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) ){
Changes to src/parse.y.
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203







-
+







createkw(A) ::= CREATE(A).  {disableLookaside(pParse);}

%type ifnotexists {int}
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
temp(A) ::= TEMP.  {A = 1;}
temp(A) ::= TEMP.  {A = pParse->db->init.busy==0;}
%endif  SQLITE_OMIT_TEMPDB
temp(A) ::= .      {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
  sqlite3EndTable(pParse,&X,&E,F,0);
}
create_table_args ::= AS select(S). {
  sqlite3EndTable(pParse,0,0,0,S);
1797
1798
1799
1800
1801
1802
1803

1804




1805
1806
1807
1808
1809
1810
1811
1797
1798
1799
1800
1801
1802
1803
1804

1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815







+
-
+
+
+
+









%type window_clause {Window*}
%destructor window_clause {sqlite3WindowListDelete(pParse->db, $$);}
window_clause(A) ::= WINDOW windowdefn_list(B). { A = B; }

filter_over(A) ::= filter_clause(F) over_clause(O). {
  if( O ){
  O->pFilter = F;
    O->pFilter = F;
  }else{
    sqlite3ExprDelete(pParse->db, F);
  }
  A = O;
}
filter_over(A) ::= over_clause(O). {
  A = O;
}
filter_over(A) ::= filter_clause(F). {
  A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
Changes to src/prepare.c.
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149







+







-







  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==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
  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
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460









461
462
463
464
465
466
467
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







-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+







      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM_BKPT;
    sqlite3ResetAllSchemasOfConnection(db);
  }
  }else
  if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
    /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
    ** the schema loaded, even if errors 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.
    /* 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;
  }

  if( rc==SQLITE_OK && iDb!=1 && IsSharedSchema(db) ){
    rc = sqlite3SchemaConnect(db, iDb, initData.cksum);
604
605
606
607
608
609
610

611
612
613
614
615
616
617
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620







+







    /* If there is not already a read-only (or read-write) transaction opened
    ** on the b-tree database, open one now. If a transaction is opened, it 
    ** will be closed immediately after reading the meta-value. */
    if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
      rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
      if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
        sqlite3OomFault(db);
        pParse->rc = SQLITE_NOMEM;
      }
      if( rc!=SQLITE_OK ) return;
      openedTransaction = 1;
    }

    /* Read the schema cookie from the database. If it does not match the 
    ** value stored as part of the in-memory schema representation,
839
840
841
842
843
844
845

846
847
848
849
850
851
852
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856







+







  }

  if( db->init.busy==0 ){
    sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
  }
  if( db->mallocFailed ){
    sParse.rc = SQLITE_NOMEM_BKPT;
    sParse.checkSchema = 0;
  }
  if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
    if( sParse.checkSchema ){
      schemaIsValid(&sParse);
    }
    if( sParse.pVdbe ){
      sqlite3VdbeFinalize(sParse.pVdbe);
Changes to src/printf.c.
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39







-
+







#define etPERCENT     7 /* Percent symbol. %% */
#define etCHARX       8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etSQLESCAPE   9 /* Strings with '\'' doubled.  %q */
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
                          NULL pointers replaced by SQL NULL.  %Q */
#define etTOKEN      11 /* a pointer to a Token structure */
#define etSRCLIST    12 /* a pointer to a SrcList */
#define etSRCITEM    12 /* a pointer to a SrcItem */
#define etPOINTER    13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL    15 /* %r -> 1st, 2nd, 3rd, 4th, etc.  English only */
#define etDECIMAL    16 /* %d or %u, but not %x, %o */

#define etINVALID    17 /* Any unrecognized conversion type */

91
92
93
94
95
96
97
98

99
100






101
102
103
104
105
106
107
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113







-
+


+
+
+
+
+
+







  {  'i', 10, 1, etDECIMAL,    0,  0 },
  {  'n',  0, 0, etSIZE,       0,  0 },
  {  '%',  0, 0, etPERCENT,    0,  0 },
  {  'p', 16, 0, etPOINTER,    0,  1 },

  /* All the rest are undocumented and are for internal use only */
  {  'T',  0, 0, etTOKEN,      0,  0 },
  {  'S',  0, 0, etSRCLIST,    0,  0 },
  {  'S',  0, 0, etSRCITEM,    0,  0 },
  {  'r', 10, 1, etORDINAL,    0,  0 },
};

/* Notes:
**
**    %S    Takes a pointer to SrcItem.  Shows name or database.name
**    %!S   Like %S but prefer the zName over the zAlias
*/

/* Floating point constants used for rounding */
static const double arRound[] = {
  5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
  5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
};

849
850
851
852
853
854
855
856

857
858
859
860
861

862
863
864
865
866
867
868
869
870













871
872
873
874
875
876
877
855
856
857
858
859
860
861

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







-
+
-
-


-
+
-
-

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+







        assert( bArgList==0 );
        if( pToken && pToken->n ){
          sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
        }
        length = width = 0;
        break;
      }
      case etSRCLIST: {
      case etSRCITEM: {
        SrcList *pSrc;
        int k;
        SrcItem *pItem;
        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
        pSrc = va_arg(ap, SrcList*);
        pItem = va_arg(ap, SrcItem*);
        k = va_arg(ap, int);
        pItem = &pSrc->a[k];
        assert( bArgList==0 );
        assert( k>=0 && k<pSrc->nSrc );
        if( pItem->zDatabase ){
          sqlite3_str_appendall(pAccum, pItem->zDatabase);
          sqlite3_str_append(pAccum, ".", 1);
        }
        sqlite3_str_appendall(pAccum, pItem->zName);
        if( pItem->zAlias && !flag_altform2 ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
        }else if( pItem->zName ){
          if( pItem->zDatabase ){
            sqlite3_str_appendall(pAccum, pItem->zDatabase);
            sqlite3_str_append(pAccum, ".", 1);
          }
          sqlite3_str_appendall(pAccum, pItem->zName);
        }else if( pItem->zAlias ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
        }else if( ALWAYS(pItem->pSelect) ){
          sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
        }
        length = width = 0;
        break;
      }
      default: {
        assert( xtype==etINVALID );
        return;
      }
Changes to src/resolve.c.
77
78
79
80
81
82
83


84


85
86
87
88
89
90
91
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94







+
+
-
+
+







  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);
  if( pDup!=0 ){
    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,
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
102
103
104
105
106
107
108

109
110


111
112
113
114
115
116
117







-
+

-
-







    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( pExpr->y.pWin!=0 ){
      if( ALWAYS(pExpr->y.pWin!=0) ){
        pExpr->y.pWin->pOwner = pExpr;
      }else{
        assert( db->mallocFailed );
      }
    }
    sqlite3DbFree(db, pDup);
  }
}


372
373
374
375
376
377
378







379

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
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







+
+
+
+
+
+
+
-
+





-
-
-







    */
    if( cnt==0 && zDb==0 ){
      pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
      if( pParse->pTriggerTab!=0 ){
        int op = pParse->eTriggerOp;
        assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
        if( pParse->bReturning ){
          if( (pNC->ncFlags & NC_UBaseReg)!=0
           && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
          ){
            pExpr->iTable = op!=TK_DELETE;
            pTab = pParse->pTriggerTab;
          }
        if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
        }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
          pExpr->iTable = 1;
          pTab = pParse->pTriggerTab;
        }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
          pExpr->iTable = 0;
          pTab = pParse->pTriggerTab;
        }else if( pParse->bReturning && (pNC->ncFlags & NC_UBaseReg)!=0 ){
          pExpr->iTable = op!=TK_DELETE;
          pTab = pParse->pTriggerTab;
        }
      }
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
      if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
        Upsert *pUpsert = pNC->uNC.pUpsert;
        if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
490
491
492
493
494
495
496

497

498
499
500
501
502
503
504
505
495
496
497
498
499
500
501
502

503

504
505
506
507
508
509
510







+
-
+
-







    **
    ** 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
    if( (pNC->ncFlags & NC_UEList)!=0
     && (pNC->ncFlags & NC_UEList)!=0
     && cnt==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
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
560
561
562
563
564
565
566

567
568
569
570
571
572
573
574
575
576
577
578
579
580





581
582
583
584
585
586
587







-














-
-
-
-
-







  ** Because no reference was made to outer contexts, the pNC->nRef
  ** fields are not changed in any context.
  */
  if( cnt==0 && zTab==0 ){
    assert( pExpr->op==TK_ID );
    if( ExprHasProperty(pExpr,EP_DblQuoted)
     && areDoubleQuotedStringsEnabled(db, pTopNC)
     && (db->init.bDropColumn==0 || sqlite3StrICmp(zCol, db->init.azInit[0])!=0)
    ){
      /* If a double-quoted identifier does not match any known column name,
      ** then treat it as a string.
      **
      ** This hack was added in the early days of SQLite in a misguided attempt
      ** to be compatible with MySQL 3.x, which used double-quotes for strings.
      ** I now sorely regret putting in this hack. The effect of this hack is
      ** that misspelled identifier names are silently converted into strings
      ** rather than causing an error, to the frustration of countless
      ** programmers. To all those frustrated programmers, my apologies.
      **
      ** Someday, I hope to get rid of this hack. Unfortunately there is
      ** a huge amount of legacy SQL that uses it. So for now, we just
      ** issue a warning.
      **
      ** 2021-03-15: ticket 1c24a659e6d7f3a1
      ** Do not do the ID-to-STRING conversion when doing the schema
      ** sanity check following a DROP COLUMN if the identifer name matches
      ** the name of the column being dropped.
      */
      sqlite3_log(SQLITE_WARNING,
        "double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
      sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
      pExpr->op = TK_STRING;
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
604
605
606
607
608
609
610

611
612
613
614
615
616
617
618







-
+







      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->nErr++;
    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.
  **
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
911
912
913
914
915
916
917

918
919
920
921
922
923
924
925







-
+







          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->nErr++;
              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
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
933
934
935
936
937
938
939

940
941
942
943
944
945
946
947







-
+







#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->nErr++;
              pNC->nNcErr++;
            }
            pExpr->op = TK_NULL;
            return WRC_Prune;
          }
        }
#endif
        if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
1025
1026

1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
989
990
991
992
993
994
995

996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
1022
1023
1024

1025
1026
1027
1028

1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044







-
+












-
+





-
+









-
+



-
+







-
+







          || (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->nErr++;
          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->nErr++;
          pNC->nNcErr++;
          is_agg = 0;
        }
#else
        if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
          sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
          pNC->nErr++;
          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->nErr++;
          pNC->nNcErr++;
        }else if( wrong_num_args ){
          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
               nId, zId);
          pNC->nErr++;
          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->nErr++;
          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
1255
1256
1257
1258
1259
1260
1261
1262
1263


1264
1265
1266
1267
1268
1269
1270
1254
1255
1256
1257
1258
1259
1260


1261
1262
1263
1264
1265
1266
1267
1268
1269







-
-
+
+








  /* 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.nErr = 0;
  nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect;
  nc.nNcErr = 0;
  db = pParse->db;
  savedSuppErr = db->suppressErr;
  if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
  rc = sqlite3ResolveExprNames(&nc, pE);
  db->suppressErr = savedSuppErr;
  if( rc ) return 0;

1515
1516
1517
1518
1519
1520
1521
1522

1523
1524
1525
1526
1527
1528
1529
1514
1515
1516
1517
1518
1519
1520

1521
1522
1523
1524
1525
1526
1527
1528







-
+







){
  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 */

  if( pOrderBy==0 ) return 0;
  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' ){
1605
1606
1607
1608
1609
1610
1611

1612

1613
1614
1615
1616
1617
1618
1619
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620







+

+








  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;
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704





1705


1706
1707
1708
1709
1710
1711
1712
1681
1682
1683
1684
1685
1686
1687







1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711
1712







-
-
-
-
-
-
-











+
+
+
+
+
-
+
+







    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;
    }
  
    /* If a HAVING clause is present, then there must be a GROUP BY clause.
    */
    if( p->pHaving && !pGroupBy ){
      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
      return WRC_Abort;
    }
  
    /* 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->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) 
1738
1739
1740
1741
1742
1743
1744

1745

1746
1747
1748
1749
1750
1751
1752
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
1753







+
-
+







    ** 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
    if( isCompound<=nCompound  /* Defer right-most ORDER BY of a compound */
     && 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;
    }
1862
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888

1889
1890
1891
1892
1893
1894
1895
1896







-
+


















-
+







  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 = resolveSelectStep;
  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->nErr>0 || w.pParse->nErr>0;
  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.
*/
1926
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
1941







-
+







    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( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
    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
Changes to src/select.c.
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
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
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
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







-
-
-
-
+
+
+
+
+

+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

+


+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  if( iOffset>0 ){
    sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
    VdbeComment((v, "OFFSET"));
  }
}

/*
** Add code that will check to make sure the N registers starting at iMem
** form a distinct entry.  iTab is a sorting index that holds previously
** seen combinations of the N values.  A new entry is made in iTab
** if the current N values are new.
** Add code that will check to make sure the array of registers starting at
** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
** distinct aggregates ("SELECT count(DISTINCT <expr>) ..."). Three strategies
** are available. Which is used depends on the value of parameter eTnctType,
** as follows:
**
**   WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
**     Build an ephemeral table that contains all entries seen before and
**     skip entries which have been seen before.
**
**     Parameter iTab is the cursor number of an ephemeral table that must
**     be opened before the VM code generated by this routine is executed.
**     The ephemeral cursor table is queried for a record identical to the
**     record formed by the current array of registers. If one is found,
** A jump to addrRepeat is made and the N+1 values are popped from the
** stack if the top N elements are not distinct.
**     jump to VM address addrRepeat. Otherwise, insert a new record into
**     the ephemeral cursor and proceed.
**
**     The returned value in this case is a copy of parameter iTab.
**
**   WHERE_DISTINCT_ORDERED:
**     In this case rows are being delivered sorted order. The ephermal
**     table is not required. Instead, the current set of values
**     is compared against previous row. If they match, the new row
**     is not distinct and control jumps to VM address addrRepeat. Otherwise,
**     the VM program proceeds with processing the new row.
**
**     The returned value in this case is the register number of the first
**     in an array of registers used to store the previous result row so that
**     it can be compared to the next. The caller must ensure that this
**     register is initialized to NULL.  (The fixDistinctOpenEph() routine
**     will take care of this initialization.)
**
**   WHERE_DISTINCT_UNIQUE:
**     In this case it has already been determined that the rows are distinct.
**     No special action is required. The return value is zero.
**
** Parameter pEList is the list of expressions used to generated the 
** contents of each row. It is used by this routine to determine (a) 
** how many elements there are in the array of registers and (b) the 
** collation sequences that should be used for the comparisons if 
** eTnctType is WHERE_DISTINCT_ORDERED.
*/
static void codeDistinct(
static int codeDistinct(
  Parse *pParse,     /* Parsing and code generating context */
  int eTnctType,     /* WHERE_DISTINCT_* value */
  int iTab,          /* A sorting index used to test for distinctness */
  int addrRepeat,    /* Jump to here if not distinct */
  ExprList *pEList,  /* Expression for each element */
  int regElem        /* First element */
){
  int iRet = 0;
  int nResultCol = pEList->nExpr;
  Vdbe *v = pParse->pVdbe;
  int N,             /* Number of elements */
  int iMem           /* First element */

  switch( eTnctType ){
    case WHERE_DISTINCT_ORDERED: {
      int i;
      int iJump;              /* Jump destination */
      int regPrev;            /* Previous row content */

      /* Allocate space for the previous row */
      iRet = regPrev = pParse->nMem+1;
      pParse->nMem += nResultCol;

      iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
      for(i=0; i<nResultCol; i++){
        CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
        if( i<nResultCol-1 ){
          sqlite3VdbeAddOp3(v, OP_Ne, regElem+i, iJump, regPrev+i);
          VdbeCoverage(v);
        }else{
          sqlite3VdbeAddOp3(v, OP_Eq, regElem+i, addrRepeat, regPrev+i);
          VdbeCoverage(v);
         }
        sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
        sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
      }
      assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
      sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1);
      break;
    }

    case WHERE_DISTINCT_UNIQUE: {
      /* nothing to do */
      break;
    }

    default: {
      int r1 = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol);
      VdbeCoverage(v);
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol);
      sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
      sqlite3ReleaseTempReg(pParse, r1);
      iRet = iTab;
      break;
    }
  }

  return iRet;
}

/*
** This routine runs after codeDistinct().  It makes necessary
** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
** routine made use of.  This processing must be done separately since
** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
** laid down.
**
** WHERE_DISTINCT_NOOP:
** WHERE_DISTINCT_UNORDERED:
**
**     No adjustments necessary.  This function is a no-op.
**
** WHERE_DISTINCT_UNIQUE:
**
**     The ephemeral table is not needed.  So change the
**     OP_OpenEphemeral opcode into an OP_Noop.
**
** WHERE_DISTINCT_ORDERED:
**
**     The ephemeral table is not needed.  But we do need register
**     iVal to be initialized to NULL.  So change the OP_OpenEphemeral
**     into an OP_Null on the iVal register.
*/
static void fixDistinctOpenEph(
  Parse *pParse,     /* Parsing and code generating context */
  int eTnctType,     /* WHERE_DISTINCT_* value */
  int iVal,          /* Value returned by codeDistinct() */
  int iOpenEphAddr   /* Address of OP_OpenEphemeral instruction for iTab */
){
  Vdbe *v;
  int r1;

  v = pParse->pVdbe;
  if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
    Vdbe *v = pParse->pVdbe;
  r1 = sqlite3GetTempReg(pParse);
  sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
  sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
  sqlite3ReleaseTempReg(pParse, r1);
    sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
    if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
      sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
    }
    if( eTnctType==WHERE_DISTINCT_ORDERED ){
      /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared 
      ** bit on the first register of the previous value.  This will cause the
      ** OP_Ne added in codeDistinct() to always fail on the first iteration of
      ** the loop even if the first row is all NULLs.  */
      VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
      pOp->opcode = OP_Null;
      pOp->p1 = 1;
      pOp->p2 = iVal;
    }
  }
}

#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/*
** This function is called as part of inner-loop generation for a SELECT
** statement with an ORDER BY that is not optimized by an index. It 
** determines the expressions, if any, that the sorter-reference 
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021

1022
1023
1024
1025


1026
1027
1028
1029
1030
1031
1032

1033
1034
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
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1133
1134
1135
1136
1137
1138
1139

1140





1141




1142
1143







1144




































1145
1146
1147
1148
1149
1150
1151







-
+
-
-
-
-
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







  }

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
    switch( pDistinct->eTnctType ){
    int eType = pDistinct->eTnctType;
      case WHERE_DISTINCT_ORDERED: {
        VdbeOp *pOp;            /* No longer required OpenEphemeral instr. */
        int iJump;              /* Jump destination */
        int regPrev;            /* Previous row content */

    int iTab = pDistinct->tabTnct;
        /* Allocate space for the previous row */
        regPrev = pParse->nMem+1;
        pParse->nMem += nResultCol;

    assert( nResultCol==p->pEList->nExpr );
    iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
        /* Change the OP_OpenEphemeral coded earlier to an OP_Null
        ** sets the MEM_Cleared bit on the first register of the
        ** previous value.  This will cause the OP_Ne below to always
        ** fail on the first iteration of the loop even if the first
        ** row is all NULLs.
        */
        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
    fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
        pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
        pOp->opcode = OP_Null;
        pOp->p1 = 1;
        pOp->p2 = regPrev;
        pOp = 0;  /* Ensure pOp is not used after sqlite3VdbeAddOp() */

        iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
        for(i=0; i<nResultCol; i++){
          CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
          if( i<nResultCol-1 ){
            sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
            VdbeCoverage(v);
          }else{
            sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
            VdbeCoverage(v);
           }
          sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
          sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
        }
        assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
        sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
        break;
      }

      case WHERE_DISTINCT_UNIQUE: {
        sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
        break;
      }

      default: {
        assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
                     regResult);
        break;
      }
    }
    if( pSort==0 ){
      codeOffset(v, p->iOffset, iContinue);
    }
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
1727
1728
1729
1730
1731
1732
1733
1734







1735
1736
1737
1738
1739
1740
1741
1803
1804
1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823







-
+
+
+
+
+
+
+








      assert( pTab && pExpr->y.pTab==pTab );
      if( pS ){
        /* The "table" is actually a sub-select or a view in the FROM clause
        ** of the SELECT statement. Return the declaration type and origin
        ** data for the result-set column of the sub-select.
        */
        if( iCol>=0 && iCol<pS->pEList->nExpr ){
        if( iCol<pS->pEList->nExpr
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
         && iCol>=0
#else
         && ALWAYS(iCol>=0)
#endif
        ){ 
          /* If iCol is less than zero, then the expression requests the
          ** rowid of the sub-select or view. This expression is legal (see 
          ** test case misc2.2.2) - it always evaluates to NULL.
          */
          NameContext sNC;
          Expr *p = pS->pEList->a[iCol].pExpr;
          sNC.pSrcList = pS->pSrc;
2657
2658
2659
2660
2661
2662
2663
2664

2665
2666
2667
2668
2669
2670
2671
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748
2749
2750
2751
2752
2753







-
+







#endif

    /* Generate code for the left and right SELECT statements.
    */
    switch( p->op ){
      case TK_ALL: {
        int addr = 0;
        int nLimit;
        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 ){
3458
3459
3460
3461
3462
3463
3464



3465
3466
3467
3468
3469
3470
3471
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556







+
+
+







  /* 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
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522



3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541




3542

3543
3544
3545

3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560







3561
3562
3563
3564
3565
3566
3567
3568
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607

3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633

3634
3635
3636

3637
3638
3639
3640
3641
3642
3643
3644








3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658







+


-
+
+
+



















+
+
+
+
-
+


-
+







-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-







  ){
    pExpr->iRightJoinTable = pSubst->iNewTable;
  }
  if( pExpr->op==TK_COLUMN
   && pExpr->iTable==pSubst->iTable
   && !ExprHasProperty(pExpr, EP_FixedCol)
  ){
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
    if( pExpr->iColumn<0 ){
      pExpr->op = TK_NULL;
    }else{
    }else
#endif
    {
      Expr *pNew;
      Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
      Expr ifNullRow;
      assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
      assert( pExpr->pRight==0 );
      if( sqlite3ExprIsVector(pCopy) ){
        sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
      }else{
        sqlite3 *db = pSubst->pParse->db;
        if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
          memset(&ifNullRow, 0, sizeof(ifNullRow));
          ifNullRow.op = TK_IF_NULL_ROW;
          ifNullRow.pLeft = pCopy;
          ifNullRow.iTable = pSubst->iNewTable;
          ifNullRow.flags = EP_IfNullRow;
          pCopy = &ifNullRow;
        }
        testcase( ExprHasProperty(pCopy, EP_Subquery) );
        pNew = sqlite3ExprDup(db, pCopy, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pNew);
          return pExpr;
        }
        if( pNew && pSubst->isLeftJoin ){
        if( pSubst->isLeftJoin ){
          ExprSetProperty(pNew, EP_CanBeNull);
        }
        if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
        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 ){
          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);
        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);
3673
3674
3675
3676
3677
3678
3679



3680

3681
3682
3683
3684
3685
3686
3687
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772

3773
3774
3775
3776
3777
3778
3779
3780







+
+
+
-
+







  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] = pParse->nTab++;
      pItem->iCursor = aCsrMap[pItem->iCursor];
      for(p=pItem->pSelect; p; p=p->pPrior){
        srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
      }
    }
  }
}

4113
4114
4115
4116
4117
4118
4119
4120

4121
4122
4123
4124
4125
4126
4127
4206
4207
4208
4209
4210
4211
4212

4213
4214
4215
4216
4217
4218
4219
4220







-
+







    p->pOrderBy = pOrderBy;
    p->op = TK_ALL;
    pSubitem->pTab = pItemTab;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
      pNew->selId = ++pParse->nSelect;
      if( aCsrMap && db->mallocFailed==0 ){
      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"
5154
5155
5156
5157
5158
5159
5160


5161





5162
5163
5164
5165
5166
5167
5168
5247
5248
5249
5250
5251
5252
5253
5254
5255

5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267







+
+
-
+
+
+
+
+







  }else{
    pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
  }
  while( pSel->pPrior ){ pSel = pSel->pPrior; }
  sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
  pTab->iPKey = -1;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
  /* The usual case - do not allow ROWID on a subquery */
  pTab->tabFlags |= TF_Ephemeral;
  pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
  pTab->tabFlags |= TF_Ephemeral;  /* Legacy compatibility mode */
#endif


  return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}

/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
5641
5642
5643
5644
5645
5646
5647
5648
5649




5650
5651
5652
5653
5654
5655
5656
5740
5741
5742
5743
5744
5745
5746


5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757







-
-
+
+
+
+







      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
        sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
                          (char*)pKeyInfo, P4_KEYINFO);
        pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, 
            pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
        ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
                          pFunc->pFunc->zName));
      }
    }
  }
}

/*
** Invoke the OP_AggFinalize opcode for every aggregate function
5674
5675
5676
5677
5678
5679
5680
5681






5682
5683
5684
5685
5686
5687
5688
5775
5776
5777
5778
5779
5780
5781

5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794







-
+
+
+
+
+
+







** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
static void updateAccumulator(
  Parse *pParse, 
  int regAcc, 
  AggInfo *pAggInfo,
  int eDistinctType
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
  struct AggInfo_func *pF;
  struct AggInfo_col *pC;

5720
5721
5722
5723
5724
5725
5726
5727

5728
5729
5730
5731

5732
5733

5734
5735
5736
5737
5738
5739
5740
5826
5827
5828
5829
5830
5831
5832

5833
5834
5835
5836

5837


5838
5839
5840
5841
5842
5843
5844
5845







-
+



-
+
-
-
+







      nArg = pList->nExpr;
      regAgg = sqlite3GetTempRange(pParse, nArg);
      sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
    }else{
      nArg = 0;
      regAgg = 0;
    }
    if( pF->iDistinct>=0 ){
    if( pF->iDistinct>=0 && pList ){
      if( addrNext==0 ){ 
        addrNext = sqlite3VdbeMakeLabel(pParse);
      }
      testcase( nArg==0 );  /* Error condition */
      pF->iDistinct = codeDistinct(pParse, eDistinctType, 
      testcase( nArg>1 );   /* Also an error */
      codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
          pF->iDistinct, addrNext, pList, regAgg);
    }
    if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
      CollSeq *pColl = 0;
      struct ExprList_item *pItem;
      int j;
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
5778
5779
5780
5781
5782
5783
5784
5785

5786
5787
5788
5789
5790
5791
5792
5883
5884
5885
5886
5887
5888
5889

5890
5891
5892
5893
5894
5895
5896
5897







-
+







static void explainSimpleCount(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being queried */
  Index *pIdx                     /* Index used to optimize scan, or NULL */
){
  if( pParse->explain==2 ){
    int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
    sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
    sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
        pTab->zName,
        bCover ? " USING COVERING INDEX " : "",
        bCover ? pIdx->zName : ""
    );
  }
}
#else
6093
6094
6095
6096
6097
6098
6099
6100

6101
6102
6103
6104
6105
6106
6107
6108
6198
6199
6200
6201
6202
6203
6204

6205

6206
6207
6208
6209
6210
6211
6212







-
+
-







  }

  if( pDest->eDest==SRT_Output ){
    generateColumnNames(pParse, p);
  }

#ifndef SQLITE_OMIT_WINDOWFUNC
  rc = sqlite3WindowRewrite(pParse, p);
  if( sqlite3WindowRewrite(pParse, p) ){
  if( rc ){
    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);
6351
6352
6353
6354
6355
6356
6357
6358

6359
6360
6361

6362
6363
6364
6365
6366
6367
6368
6455
6456
6457
6458
6459
6460
6461

6462
6463
6464

6465
6466
6467
6468
6469
6470
6471
6472







-
+


-
+







      /* Implement a co-routine that will return a single row of the result
      ** set on each invocation.
      */
      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
     
      pItem->regReturn = ++pParse->nMem;
      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
      VdbeComment((v, "%s", pItem->pTab->zName));
      VdbeComment((v, "%!S", pItem));
      pItem->addrFillSub = addrTop;
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
      pItem->fg.viaCoroutine = 1;
      pItem->regResult = dest.iSdst;
      sqlite3VdbeEndCoroutine(v, pItem->regReturn);
      sqlite3VdbeJumpHere(v, addrTop-1);
      sqlite3ClearTempRegCache(pParse);
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
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







-
+

-
+


-
+




-
+







      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      pItem->addrFillSub = topAddr+1;
      if( pItem->fg.isCorrelated==0 ){
        /* If the subquery is not correlated and if we are not inside of
        ** a trigger, then we only need to compute the value of the subquery
        ** once. */
        onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
        VdbeComment((v, "materialize %!S", pItem));
      }else{
        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
        VdbeNoopComment((v, "materialize %!S", pItem));
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
      ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
      VdbeComment((v, "end %s", pItem->pTab->zName));
      VdbeComment((v, "end %!S", pItem));
      sqlite3VdbeChangeP1(v, topAddr, retAddr);
      sqlite3ClearTempRegCache(pParse);
      if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
        CteUse *pCteUse = pItem->u2.pCteUse;
        pCteUse->addrM9e = pItem->addrFillSub;
        pCteUse->regRtn = pItem->regReturn;
        pCteUse->iCur = pItem->iCursor;
6758
6759
6760
6761
6762
6763
6764














6765
6766
6767
6768
6769
6770
6771
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889







+
+
+
+
+
+
+
+
+
+
+
+
+
+







      int addrOutputRow;  /* Start of subroutine that outputs a result row */
      int regOutputRow;   /* Return address register for output subroutine */
      int addrSetAbort;   /* Set the abort flag and return */
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */
      ExprList *pDistinct = 0;
      u16 distFlag = 0;
      int eDist = WHERE_DISTINCT_NOOP;

      if( pAggInfo->nFunc==1 
       && pAggInfo->aFunc[0].iDistinct>=0
       && pAggInfo->aFunc[0].pFExpr->x.pList
      ){
        Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
        pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
        distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
      }

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      pAggInfo->sortingIdx = pParse->nTab++;
6794
6795
6796
6797
6798
6799
6800
6801
6802


6803
6804





6805
6806
6807
6808
6809
6810
6811
6912
6913
6914
6915
6916
6917
6918


6919
6920
6921

6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933







-
-
+
+

-
+
+
+
+
+







      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      SELECTTRACE(1,pParse,p,("WhereBegin\n"));
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
          WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
          WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
      );
      if( pWInfo==0 ) goto select_end;
      if( pWInfo==0 ){
        sqlite3ExprListDelete(db, pDistinct);
        goto select_end;
      }
      eDist = sqlite3WhereIsDistinct(pWInfo);
      SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
      if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        groupBySort = 0;
6915
6916
6917
6918
6919
6920
6921
6922

6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935

6936
6937
6938
6939
6940
6941
6942
7037
7038
7039
7040
7041
7042
7043

7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065







-
+













+







      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      VdbeComment((v, "reset accumulator"));

      /* Update the aggregate accumulators based on the content of
      ** the current row
      */
      sqlite3VdbeJumpHere(v, addr1);
      updateAccumulator(pParse, iUseFlag, pAggInfo);
      updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
        VdbeCoverage(v);
      }else{
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
      }
      sqlite3ExprListDelete(db, pDistinct);

      /* Output the final row of result
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));

      /* Jump over the subroutines
6971
6972
6973
6974
6975
6976
6977
6978





6979
6980
6981
6982
6983
6984
6985
7094
7095
7096
7097
7098
7099
7100

7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112







-
+
+
+
+
+







      /* Generate a subroutine that will reset the group-by accumulator
      */
      sqlite3VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, pAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
      VdbeComment((v, "indicate accumulator empty"));
      sqlite3VdbeAddOp1(v, OP_Return, regReset);
     

      if( eDist!=WHERE_DISTINCT_NOOP ){
        struct AggInfo_func *pF = &pAggInfo->aFunc[0];
        fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
      }
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      Table *pTab;
      if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
        /* If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **
7035
7036
7037
7038
7039
7040
7041



7042
7043
7044
7045
7046
7047
7048
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178







+
+
+







          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
        }
        sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
        sqlite3VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else{
        int regAcc = 0;           /* "populate accumulators" flag */
        ExprList *pDistinct = 0;
        u16 distFlag = 0;
        int eDist;

        /* If there are accumulator registers but no min() or max() functions
        ** without FILTER clauses, allocate register regAcc. Register regAcc
        ** will contain 0 the first time the inner loop runs, and 1 thereafter.
        ** The code generated by updateAccumulator() uses this to ensure
        ** that the accumulator registers are (a) updated only once if
        ** there are no min() or max functions or (b) always updated for the
7058
7059
7060
7061
7062
7063
7064



7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084

7085
7086
7087
7088

7089






7090
7091
7092
7093
7094
7095
7096
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216

7217
7218
7219
7220
7221
7222

7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235







+
+
+



















-
+




+
-
+
+
+
+
+
+







              break;
            }
          }
          if( i==pAggInfo->nFunc ){
            regAcc = ++pParse->nMem;
            sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
          }
        }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
          pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
          distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
        }

        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        assert( p->pGroupBy==0 );
        resetAccumulator(pParse, pAggInfo);

        /* If this query is a candidate for the min/max optimization, then
        ** minMaxFlag will have been previously set to either
        ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
        ** be an appropriate ORDER BY expression for the optimization.
        */
        assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
        assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );

        SELECTTRACE(1,pParse,p,("WhereBegin\n"));
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
                                   0, minMaxFlag, 0);
                                   pDistinct, minMaxFlag|distFlag, 0);
        if( pWInfo==0 ){
          goto select_end;
        }
        SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
        eDist = sqlite3WhereIsDistinct(pWInfo);
        updateAccumulator(pParse, regAcc, pAggInfo);
        updateAccumulator(pParse, regAcc, pAggInfo, eDist);
        if( eDist!=WHERE_DISTINCT_NOOP ){
          struct AggInfo_func *pF = &pAggInfo->aFunc[0];
          fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
        }

        if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
        if( minMaxFlag ){
          sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
        }
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, pAggInfo);
7127
7128
7129
7130
7131
7132
7133


7134
7135
7136
7137
7138
7139
7140
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281







+
+







  ** 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 );
Changes to src/shell.c.in.
2912
2913
2914
2915
2916
2917
2918
2919

2920
2921
2922
2923
2924
2925
2926
2912
2913
2914
2915
2916
2917
2918

2919
2920
2921
2922
2923
2924
2925
2926







-
+







  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
  sqlite3_exec(p->db,
    "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
    "  key TEXT PRIMARY KEY,\n"
    "  value ANY\n"
    "  value\n"
    ") WITHOUT ROWID;",
    0, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
}

/*
5787
5788
5789
5790
5791
5792
5793
5794

5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814

5815
5816
5817
5818
5819
5820
5821
5787
5788
5789
5790
5791
5792
5793

5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813

5814
5815
5816
5817
5818
5819
5820
5821







-
+



















-
+







  const char *zSql =
  "SELECT "
    "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
    "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
    "  || fkey_collate_clause("
    "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
    ", "
    "     'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
    "     'SEARCH ' || s.name || ' USING COVERING INDEX*('"
    "  || group_concat('*=?', ' AND ') || ')'"
    ", "
    "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
    ", "
    "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
    ", "
    "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
    "  || ' ON ' || quote(s.name) || '('"
    "  || group_concat(quote(f.[from]) ||"
    "        fkey_collate_clause("
    "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
    "  || ');'"
    ", "
    "     f.[table] "
    "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
    "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
    "GROUP BY s.name, f.id "
    "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
  ;
  const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
  const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";

  for(i=2; i<nArg; i++){
    int n = strlen30(azArg[i]);
    if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
      bVerbose = 1;
    }
    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6725
6726
6727
6728
6729
6730
6731

6732
6733
6734
6735
6736
6737
6738
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739







+







  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.
*/
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8261
8262
8263
8264
8265
8266
8267

8268
8269
8270
8271
8272
8273
8274







-







      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;
    char *zErrMsg = 0;
    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;
8282
8283
8284
8285
8286
8287
8288
8289

8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305

8306
8307
8308

8309
8310

8311
8312
8313
8314
8315
8316
8317
8282
8283
8284
8285
8286
8287
8288

8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304

8305
8306
8307

8308
8309

8310
8311
8312
8313
8314
8315
8316
8317







-
+















-
+


-
+

-
+







    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, &zErrMsg
       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, &zErrMsg);
                   callback, &data, 0);
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
      shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
      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]);
Changes to src/sqlite.h.in.
1125
1126
1127
1128
1129
1130
1131

















1132
1133
1134
1135
1136
1137
1138
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
** in wal mode after the client has finished copying pages from the wal
** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed.
** </ul>
**
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
** whether or not there is a database client in another process with a wal-mode 
** transaction open on the database or not. It is only available on unix.The
** (void*) argument passed with this file-control should be a pointer to a
** value of type (int). The integer value is set to 1 if the database is a wal
** mode database and there exists at least one client in another process that
** currently has an SQL transaction open on the database. It is set to 0 if 
** the database is not a wal-mode db, or if there is no such connection in any
** other process. This opcode cannot be used to detect transactions opened
** by clients within the current process, only within other processes.
** </ul>
**
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
** Used by the cksmvfs VFS module only.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
#define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
#define SQLITE_FCNTL_LAST_ERRNO              4
#define SQLITE_FCNTL_SIZE_HINT               5
#define SQLITE_FCNTL_CHUNK_SIZE              6
1164
1165
1166
1167
1168
1169
1170


1171
1172
1173
1174
1175
1176
1177
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196







+
+







#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


4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357







4358
4359
4360
4361






4362
4363



4364
4365
4366
4367
4368
4369
4370
4364
4365
4366
4367
4368
4369
4370






4371
4372
4373
4374
4375
4376
4377




4378
4379
4380
4381
4382
4383


4384
4385
4386
4387
4388
4389
4390
4391
4392
4393







-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
-
-
+
+
+







** 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
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor 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.
** ^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.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** ^(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
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
** 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
9528
9529
9530
9531
9532
9533
9534









9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554

9555
9556
9557
9558
9559
9560
9561
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
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594







+
+
+
+
+
+
+
+
+




















+







**
** ^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)
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*
);
int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
int sqlite3_preupdate_count(sqlite3 *);
int sqlite3_preupdate_depth(sqlite3 *);
int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
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
Changes to src/sqliteInt.h.
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1537
1538
1539
1540
1541
1542
1543

1544


1545
1546
1547
1548
1549
1550
1551







-

-
-







  struct sqlite3InitInfo {      /* Information used during initialization */
    Pgno newTnum;               /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
    unsigned imposterTable : 1; /* Building an imposter table */
    unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
    unsigned bDropColumn : 1;   /* Doing schema check after DROP COLUMN */
    char **azInit;              /* "type", "name", and "tbl_name" columns */
                                /*   or if bDropColumn, then azInit[0] is the */
                                /*   name of the column being dropped */
  } init;
  int nVdbeActive;              /* Number of VDBEs currently running */
  int nVdbeRead;                /* Number of active VDBEs that read or write */
  int nVdbeWrite;               /* Number of active VDBEs that read and write */
  int nVdbeExec;                /* Number of nested calls to VdbeExec() */
  int nVDestroy;                /* Number of active OP_VDestroy operations */
  int nExtension;               /* Number of loaded extensions */
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756
1757







-







#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_ExistsToIN     0x00020000 /* The EXISTS-to-IN 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)
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2116
2117
2118
2119
2120
2121
2122

2123

2124
2125
2126
2127
2128
2129
2130







-

-







** changing the affinity.
**
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
** It causes an assert() to fire if either operand to a comparison
** operator is NULL.  It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
#define SQLITE_KEEPNULL     0x08  /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL   0x10  /* jumps if either operand is NULL */
#define SQLITE_STOREP2      0x20  /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ       0x80  /* NULL=NULL */
#define SQLITE_NOTNULL      0x90  /* Assert that operands are never NULL */

/*
** An object of this type is created for each virtual table present in
** the database schema.
**
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265







+







                                     ** 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
2622
2623
2624
2625
2626
2627
2628

2629
2630
2631
2632
2633
2634
2635
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631







+







                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pFExpr;            /* Expression encoding the function */
    FuncDef *pFunc;          /* The aggregate function implementation */
    int iMem;                /* Memory location that acts as accumulator */
    int iDistinct;           /* Ephemeral table used to enforce DISTINCT */
    int iDistAddr;           /* Address of OP_OpenEphemeral */
  } *aFunc;
  int nFunc;              /* Number of entries in aFunc[] */
  u32 selId;              /* Select to which this AggInfo belongs */
};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904







+







**                     of subqueries
**
**    ENAME_SPAN       Text of the original result set
**                     expression.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int nAlloc;            /* Number of a[] slots allocated */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The parse tree for this expression */
    char *zEName;           /* Token associated with this expression */
    u8 sortFlags;           /* Mask of KEYINFO_ORDER_* flags */
    unsigned eEName :2;     /* Meaning of zEName */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned reusable :1;   /* Constant expression is reusable */
3038
3039
3040
3041
3042
3043
3044
3045

3046
3047
3048
3049
3050
3051
3052
3035
3036
3037
3038
3039
3040
3041

3042
3043
3044
3045
3046
3047
3048
3049







-
+







#define WHERE_DUPLICATES_OK    0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE     0x0020 /* Processing a sub-WHERE as part of
                                      ** the OR optimization  */
#define WHERE_GROUPBY          0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
                        /*     0x0400    not currently used */
#define WHERE_AGG_DISTINCT     0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
                        /*     0x1000    not currently used */
                        /*     0x2000    not currently used */
#define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
                        /*     0x8000    not currently used */

/* Allowed return values from sqlite3WhereIsDistinct()
3084
3085
3086
3087
3088
3089
3090
3091

3092
3093
3094
3095
3096
3097
3098
3081
3082
3083
3084
3085
3086
3087

3088
3089
3090
3091
3092
3093
3094
3095







-
+







    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 nErr;            /* Number of errors encountered while resolving names */
  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.
**
3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128







+







#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
3901
3902
3903
3904
3905
3906
3907

3908
3909
3910
3911
3912
3913
3914
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913







+







int sqlite3WalkSelectExpr(Walker*, Select*);
int sqlite3WalkSelectFrom(Walker*, Select*);
int sqlite3ExprWalkNoop(Walker*, Expr*);
int sqlite3SelectWalkNoop(Walker*, Select*);
int sqlite3SelectWalkFail(Walker*, Select*);
int sqlite3WalkerDepthIncrease(Walker*,Select*);
void sqlite3WalkerDepthDecrease(Walker*,Select*);
void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);

#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif

/*
** Return code from the parse-tree walking primitives and their
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322







+







void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
Expr *sqlite3ExprSimplifiedAndOr(Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
4759
4760
4761
4762
4763
4764
4765



4766
4767
4768
4769
4770
4771
4772
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775







+
+
+







#endif
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char *sqlite3aLTb;
extern const unsigned char *sqlite3aEQb;
extern const unsigned char *sqlite3aGTb;
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
#endif /* SQLITE_AMALGAMATION */
Changes to src/test1.c.
3821
3822
3823
3824
3825
3826
3827

3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840

3841





3842





3843

3844
3845
3846

3847
3848
3849
3850
3851
3852
3853
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841

3842
3843
3844
3845
3846
3847
3848

3849
3850
3851
3852
3853
3854
3855
3856
3857

3858
3859
3860
3861
3862
3863
3864
3865







+



+









-
+

+
+
+
+
+
-
+
+
+
+
+

+


-
+







  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int idx;
  int trueLength = 0;
  int bytes;
  char *value;
  int rc;
  char *toFree = 0;

  if( objc!=5 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
  value = (char*)Tcl_GetByteArrayFromObj(objv[3], &trueLength);
  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
  if( bytes<0 ){
    toFree = malloc( trueLength + 1 );
    if( toFree==0 ){
      Tcl_AppendResult(interp, "out of memory", (void*)0);
      return TCL_ERROR;

    }
    memcpy(toFree, value, trueLength);
    toFree[trueLength] = 0;
    value = toFree;
  }
  rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
  free(toFree);
  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
    Tcl_AppendResult(interp, sqlite3ErrName(rc), (void*)0);
    return TCL_ERROR;
  }

  return TCL_OK;
}

/*
3865
3866
3867
3868
3869
3870
3871

3872

3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888

3889





3890





3891

3892
3893
3894
3895
3896
3897
3898
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901

3902
3903
3904
3905
3906
3907
3908

3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922







+

+















-
+

+
+
+
+
+
-
+
+
+
+
+

+







  Tcl_Obj *CONST objv[]
){
#ifndef SQLITE_OMIT_UTF16
  sqlite3_stmt *pStmt;
  int idx;
  int bytes;
  char *value;
  char *toFree = 0;
  int rc;
  int trueLength = 0;

  void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
  Tcl_Obj *oStmt    = objv[objc-4];
  Tcl_Obj *oN       = objv[objc-3];
  Tcl_Obj *oString  = objv[objc-2];
  Tcl_Obj *oBytes   = objv[objc-1];

  if( objc!=5 && objc!=6){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
  value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
  value = (char*)Tcl_GetByteArrayFromObj(oString, &trueLength);
  if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
  if( bytes<0 && xDel==SQLITE_TRANSIENT ){
    toFree = malloc( trueLength + 3 );
    if( toFree==0 ){
      Tcl_AppendResult(interp, "out of memory", (void*)0);
      return TCL_ERROR;

    }
    memcpy(toFree, value, trueLength);
    memset(toFree+trueLength, 0, 3);
    value = toFree;
  }
  rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
  free(toFree);
  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
    return TCL_ERROR;
  }

#endif /* SQLITE_OMIT_UTF16 */
6486
6487
6488
6489
6490
6491
6492




































6493
6494
6495
6496
6497
6498
6499
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }
  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
  Tcl_AppendResult(interp, zTName, (char*)0);
  sqlite3_free(zTName);
  return TCL_OK;  
}

/*
** tclcmd:   file_control_external_reader DB ?AUXDB?
**
** Return a string that is a temporary filename
*/
static int SQLITE_TCLAPI file_control_external_reader(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  const char *zName = "main";
  int iRes = 0;
  int rc = SQLITE_OK;

  if( objc!=2 && objc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
    return TCL_ERROR;
  }
  if( objc==3 ){
    zName = Tcl_GetString(objv[2]);
  }
  rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
  return TCL_OK;
}


/*
** tclcmd:   sqlite3_vfs_list
**
**   Return a tcl list containing the names of all registered vfs's.
*/
static int SQLITE_TCLAPI vfs_list(
8424
8425
8426
8427
8428
8429
8430

8431
8432
8433
8434
8435
8436
8437
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498







+







     { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
#endif
     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_reservebytes",   file_control_reservebytes,    0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "file_control_external_reader",   file_control_external_reader,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },

     /* Functions from os.h */
#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
Changes to src/test_config.c.
60
61
62
63
64
65
66







67
68
69
70
71
72
73
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80







+
+
+
+
+
+
+







#endif

#ifdef SQLITE_CASE_SENSITIVE_LIKE
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
#endif

#ifdef CONFIG_SLOWDOWN_FACTOR
  Tcl_SetVar2(interp, "sqlite_options","configslower",
              STRINGVALUE(CONFIG_SLOWDOWN_FACTOR),TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options","configslower","1.0",TCL_GLOBAL_ONLY);
#endif

#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "curdir", "0", TCL_GLOBAL_ONLY);
#endif

221
222
223
224
225
226
227






228
229
230
231
232
233
234
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247







+
+
+
+
+
+







#endif

#ifdef SQLITE_ENABLE_ATOMIC_WRITE
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_GEOPOLY
  Tcl_SetVar2(interp, "sqlite_options", "geopoly", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "geopoly", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_JSON1
  Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
#endif

Changes to src/tokenize.c.
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
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







+












-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+







#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 */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* 9x */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Ax */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Bx */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Cx */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Dx */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Ex */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
/* Fx */    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2
/* 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,
528
529
530
531
532
533
534








535
536
537
538
539
540
541
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550







+
+
+
+
+
+
+
+







#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;
    }
Changes to src/treeview.c.
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
130
131
132
133
134
135
136
137

138





139
140
141
142



143
144
145
146
147
148
149







+
-
+
-
-
-
-
-




-
-
-







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:*}", pItem->iCursor);
    sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
    if( pItem->zDatabase ){
      sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
    }else if( pItem->zName ){
      sqlite3_str_appendf(&x, " %s", pItem->zName);
    }
    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->zAlias ){
      sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
    }
    if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&x, " LEFT-JOIN");
    }
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.isCte ){
Changes to src/trigger.c.
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
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







-
-
-
+
+
-
-
-
+
+

+



+

-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  HashElem *p;              /* Loop variable for TEMP triggers */

  if( pParse->disableTriggers ){
    return 0;
  }
  pTmpSchema = pParse->db->aDb[1].pSchema;
  p = sqliteHashFirst(&pTmpSchema->trigHash);
  if( p==0 ){
    return pTab->pTrigger;
  }
  pList = pTab->pTrigger;

  pList = pTab->pTrigger;
  if( pTmpSchema!=pTab->pSchema ){
    sqlite3 *db = pParse->db;
  while( p ){
    Trigger *pTrig = (Trigger *)sqliteHashData(p);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    sqlite3 *db = pParse->db;
    char *zSchema = 0;
    if( IsSharedSchema(db) ){
      zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
      assert( zSchema );
    }
#endif
    assert( sqlite3SchemaMutexHeld(db, 0, pTmpSchema) );
    if( pTab->pSchema!=pTmpSchema
    while( p ){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
      if( ( (zSchema==0 && pTrig->pTabSchema==pTab->pSchema)
         || (zSchema!=0 && 0==sqlite3StrICmp(pTrig->zTabSchema, zSchema)) 
          ) && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
      ){
#else 
      if( pTrig->pTabSchema==pTab->pSchema
       && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
      ){
     && ( (zSchema==0 && pTrig->pTabSchema==pTab->pSchema)
          || (zSchema!=0 && 0==sqlite3StrICmp(pTrig->zTabSchema, zSchema)) 
        ) && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
    ){
#else
    if( pTrig->pTabSchema==pTab->pSchema
     && pTrig->table
     && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
     && pTrig->pTabSchema!=pTmpSchema
    ){
#endif
        pTrig->pNext = pList;
        pList = pTrig;
      }else if( pTrig->op==TK_RETURNING ){
        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);    
    }
  }
      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
220
221
222
223
224
225
226
227

228
229
230
231
232

233
234
235
236
237
238
239
232
233
234
235
236
237
238

239
240
241
242
243

244
245
246
247
248
249
250
251







-
+




-
+







  }

  /* INSTEAD of triggers are only for views and views only support INSTEAD
  ** of triggers.
  */
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
    goto trigger_orphan_error;
  }
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
        " trigger on table: %S", pTableName, 0);
        " trigger on table: %S", pTableName->a);
    goto trigger_orphan_error;
  }

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( !IN_RENAME_OBJECT ){
    int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    int code = SQLITE_CREATE_TRIGGER;
631
632
633
634
635
636
637
638

639
640
641
642
643
644
645
643
644
645
646
647
648
649

650
651
652
653
654
655
656
657







-
+







    if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
    assert( sqlite3SchemaMutexHeld(db, j, 0) );
    pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
    if( pTrigger ) break;
  }
  if( !pTrigger ){
    if( !noErr ){
      sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
      sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
    }else{
      sqlite3CodeVerifyNamedSchema(pParse, zDb);
    }
    pParse->checkSchema = 1;
    goto drop_trigger_cleanup;
  }
  sqlite3DropTriggerPtr(pParse, pTrigger);
843
844
845
846
847
848
849



















850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868


869
870
871
872
873
874
875
855
856
857
858
859
860
861
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+
+







      pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
    }
  }else{
    sqlite3DbFree(db, zName);
  }
  return pSrc;
}

/*
** Return true if the pExpr term from the RETURNING clause argument
** list is of the form "*".  Raise an error if the terms if of the
** form "table.*".
*/
static int isAsteriskTerm(
  Parse *pParse,      /* Parsing context */
  Expr *pTerm         /* A term in the RETURNING clause */
){
  assert( pTerm!=0 );
  if( pTerm->op==TK_ASTERISK ) return 1;
  if( pTerm->op!=TK_DOT ) return 0;
  assert( pTerm->pRight!=0 );
  assert( pTerm->pLeft!=0 );
  if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
  sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
  return 1;
}

/* The input list pList is the list of result set terms from a RETURNING
** clause.  The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
  Parse *pParse,        /* Parsing context */
  ExprList *pList,      /* The arguments to RETURNING */
  Table *pTab           /* The table being updated */
){
  ExprList *pNew = 0;
  sqlite3 *db = pParse->db;
  int i;

  for(i=0; i<pList->nExpr; i++){
    Expr *pOldExpr = pList->a[i].pExpr;
    if( ALWAYS(pOldExpr!=0) && pOldExpr->op==TK_ASTERISK ){
    if( NEVER(pOldExpr==0) ) continue;
    if( isAsteriskTerm(pParse, pOldExpr) ){
      int jj;
      for(jj=0; jj<pTab->nCol; jj++){
        Expr *pNewExpr;
        if( IsHiddenColumn(pTab->aCol+jj) ) continue;
        pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
        pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
        if( !db->mallocFailed ){
1089
1090
1091
1092
1093
1094
1095
1096
1097



1098
1099
1100
1101
1102
1103
1104
1121
1122
1123
1124
1125
1126
1127


1128
1129
1130
1131
1132
1133
1134
1135
1136
1137







-
-
+
+
+







  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */
  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger)
       || IsSharedSchema(pParse->db)
  assert( pTrigger->zName==0 
      || IsSharedSchema(pParse->db)
      || pTab==tableOfTrigger(pTrigger)
  );
  assert( pTop->pVdbe );

  /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
  ** are freed if an error occurs, link them into the Parse.pTriggerPrg 
  ** list of the top-level Parse object sooner rather than later.  */
  pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
1146
1147
1148
1149
1150
1151
1152

1153

1154
1155
1156
1157
1158
1159
1160
1161
1179
1180
1181
1182
1183
1184
1185
1186

1187

1188
1189
1190
1191
1192
1193
1194







+
-
+
-







#endif

    /* If one was specified, code the WHEN clause. If it evaluates to false
    ** (or NULL) the sub-vdbe is immediately halted by jumping to the 
    ** OP_Halt inserted at the end of the program.  */
    if( pTrigger->pWhen ){
      pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
      if( db->mallocFailed==0
      if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) 
       && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) 
       && db->mallocFailed==0 
      ){
        iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
        sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pWhen);
    }

1199
1200
1201
1202
1203
1204
1205
1206

1207

1208
1209
1210
1211
1212
1213
1214
1232
1233
1234
1235
1236
1237
1238

1239
1240
1241
1242
1243
1244
1245
1246
1247
1248







-
+

+







  Trigger *pTrigger,   /* Trigger to code */
  Table *pTab,         /* The table trigger pTrigger is attached to */
  int orconf           /* ON CONFLICT algorithm. */
){
  Parse *pRoot = sqlite3ParseToplevel(pParse);
  TriggerPrg *pPrg;

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) 
  assert( pTrigger->zName==0 
       || IsSharedSchema(pParse->db)
       || pTab==tableOfTrigger(pTrigger) 
  );

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching TriggerPrg.pTrigger field will be present somewhere
  ** in the Parse.pTriggerPrg list. Search for such an entry.  */
  for(pPrg=pRoot->pTriggerPrg; 
Changes to src/update.c.
245
246
247
248
249
250
251

252

253
254
255
256
257
258
259
245
246
247
248
249
250
251
252

253
254
255
256
257
258
259
260







+
-
+







    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( ALWAYS(pChanges) ){
  if( pChanges ){
    for(i=0; i<pChanges->nExpr; i++){
      pList = sqlite3ExprListAppend(pParse, pList, 
          sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
      );
    }
  }
  pSelect = sqlite3SelectNew(pParse, pList, 
795
796
797
798
799
800
801

802





803
804
805
806
807
808
809
796
797
798
799
800
801
802
803

804
805
806
807
808
809
810
811
812
813
814
815







+
-
+
+
+
+
+







      if( addrOnce ){
        sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
      }
    }
  
    /* Top of the update loop */
    if( eOnePass!=ONEPASS_OFF ){
      if( aiCurOnePass[0]!=iDataCur
      if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
       && aiCurOnePass[1]!=iDataCur
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
       && !isView
#endif
      ){
        assert( pPk );
        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
        VdbeCoverage(v);
      }
      if( eOnePass!=ONEPASS_SINGLE ){
        labelContinue = sqlite3VdbeMakeLabel(pParse);
      }
Changes to src/vdbe.c.
429
430
431
432
433
434
435
436




437
438
439
440
441
442
443
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446







-
+
+
+
+







** 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 );
  ExpandBlob(pMem);
  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;
566
567
568
569
570
571
572





573
574
575
576
577
578
579
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587







+
+
+
+
+







  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.
1469
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1477
1478
1479
1480
1481
1482
1483

1484
1485
1486
1487
1488
1489
1490
1491







-
+







** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
  Mem *pMem;
  int i;
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 );
  assert( pOp->p1>0 || CORRUPT_DB );
  assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );

  /* Invalidate all ephemeral cursor row caches */
  p->cacheCtr = (p->cacheCtr + 2)|1;

  /* Make sure the results of the current row are \000 terminated
  ** and have an assigned type.  The results are de-ephemeralized as
1911
1912
1913
1914
1915
1916
1917
1918

1919
1920
1921
1922
1923
1924
1925
1926
1919
1920
1921
1922
1923
1924
1925

1926

1927
1928
1929
1930
1931
1932
1933







-
+
-







}
#endif /* SQLITE_OMIT_CAST */

/* Opcode: Eq P1 P2 P3 P4 P5
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3.  If reg(P3)==reg(P1) then
** jump to address P2.  Or if the SQLITE_STOREP2 flag is set in P5, then
** jump to address P2. 
** store the result of comparison in register P2.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3.  So this opcode can cause
1938
1939
1940
1941
1942
1943
1944
1945
1946


1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964

1965
1966
1967
1968
1969
1970
1971
1972
1945
1946
1947
1948
1949
1950
1951


1952
1953

1954
1955
1956
1957
1958
1959
1960




1961
1962
1963
1964
1965

1966

1967
1968
1969
1970
1971
1972
1973







-
-
+
+
-







-
-
-
-





-
+
-







**
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
** content of r[P2] is only changed if the new value is NULL or 0 (false).
** This opcode saves the result of comparison for use by the new
** OP_Jump opcode.
** In other words, a prior r[P2] value will not be overwritten by 1 (true).
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
**
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal.  See the Eq opcode for
** additional information.
**
** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
** content of r[P2] is only changed if the new value is NULL or 1 (true).
** In other words, a prior r[P2] value will not be overwritten by 0 (false).
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<r[P1]
**
** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
** jump to address P2.  Or if the SQLITE_STOREP2 flag is set in P5 store
** jump to address P2.
** the result of comparison (0 or 1 or NULL) into register P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then the take the jump.  If the SQLITE_JUMPIFNULL 
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
1981
1982
1983
1984
1985
1986
1987



1988
1989
1990
1991
1992
1993
1994
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998







+
+
+







** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is  used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.
**
** This opcode saves the result of comparison for use by the new
** OP_Jump opcode.
*/
/* Opcode: Le P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<=r[P1]
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1.  See the Lt opcode for additional information.
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
2044
2045
2046
2047
2048
2049
2050



2051







2052
2053
2054

2055
2056
2057
2058
2059
2060
2061







-
-
-
+
-
-
-
-
-
-
-
+
+
+
-







        res = ((flags3 & MEM_Null) ? -1 : +1);  /* Operands are not equal */
      }
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
      */
      if( pOp->p5 & SQLITE_STOREP2 ){
        pOut = &aMem[pOp->p2];
        iCompare = 1;    /* Operands are not equal */
      iCompare = 1;    /* Operands are not equal */
        memAboutToChange(p, pOut);
        MemSetTypeFlag(pOut, MEM_Null);
        REGISTER_TRACE(pOp->p2, pOut);
      }else{
        VdbeBranchTaken(2,3);
        if( pOp->p5 & SQLITE_JUMPIFNULL ){
          goto jump_to_p2;
      VdbeBranchTaken(2,3);
      if( pOp->p5 & SQLITE_JUMPIFNULL ){
        goto jump_to_p2;
        }
      }
      break;
    }
  }else{
    /* Neither operand is NULL.  Do a comparison. */
    affinity = pOp->p5 & SQLITE_AFF_MASK;
    if( affinity>=SQLITE_AFF_NUMERIC ){
2107
2108
2109
2110
2111
2112
2113
2114

2115
2116

2117
2118
2119

2120
2121
2122

2123

2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158




2159
2160
2161
2162
2163

2164
2165
2166
2167
2168

2169
2170
2171
2172
2173
2174



2175
2176

2177
2178
2179
2180
2181

2182
2183
2184
2185
2186
2187
2188
2189
2190
2191


2192
2193
2194
2195
2196
2197
2198
2104
2105
2106
2107
2108
2109
2110

2111


2112
2113


2114
2115


2116
2117
2118
2119
2120
2121
2122
2123
2124
2125




























2126
2127
2128
2129

2130
2131
2132

2133
2134
2135
2136
2137

2138

2139
2140



2141
2142
2143
2144

2145
2146
2147
2148


2149
2150
2151
2152
2153

2154
2155
2156


2157
2158
2159
2160
2161
2162
2163
2164
2165







-
+
-
-
+

-
-
+

-
-
+

+







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-



-
+




-
+
-


-
-
-
+
+
+

-
+



-
-
+




-



-
-
+
+







  ** less than, equal to, or greater than reg[P3], respectively.  Compute
  ** the answer to this operator in res2, depending on what the comparison
  ** operator actually is.  The next block of code depends on the fact
  ** that the 6 comparison operators are consecutive integers in this
  ** order:  NE, EQ, GT, LE, LT, GE */
  assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
  assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
  if( res<0 ){                        /* ne, eq, gt, le, lt, ge */
  if( res<0 ){
    static const unsigned char aLTb[] = { 1,  0,  0,  1,  1,  0 };
    res2 = aLTb[pOp->opcode - OP_Ne];
    res2 = sqlite3aLTb[pOp->opcode];
  }else if( res==0 ){
    static const unsigned char aEQb[] = { 0,  1,  0,  1,  0,  1 };
    res2 = aEQb[pOp->opcode - OP_Ne];
    res2 = sqlite3aEQb[pOp->opcode];
  }else{
    static const unsigned char aGTb[] = { 1,  0,  1,  0,  0,  1 };
    res2 = aGTb[pOp->opcode - OP_Ne];
    res2 = sqlite3aGTb[pOp->opcode];
  }
  iCompare = res;

  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;

  if( pOp->p5 & SQLITE_STOREP2 ){
    pOut = &aMem[pOp->p2];
    iCompare = res;
    if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
      /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
      ** and prevents OP_Ne from overwriting NULL with 0.  This flag
      ** is only used in contexts where either:
      **   (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
      **   (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
      ** Therefore it is not necessary to check the content of r[P2] for
      ** NULL. */
      assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
      assert( res2==0 || res2==1 );
      testcase( res2==0 && pOp->opcode==OP_Eq );
      testcase( res2==1 && pOp->opcode==OP_Eq );
      testcase( res2==0 && pOp->opcode==OP_Ne );
      testcase( res2==1 && pOp->opcode==OP_Ne );
      if( (pOp->opcode==OP_Eq)==res2 ) break;
    }
    memAboutToChange(p, pOut);
    MemSetTypeFlag(pOut, MEM_Int);
    pOut->u.i = res2;
    REGISTER_TRACE(pOp->p2, pOut);
  }else{
    VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    if( res2 ){
      goto jump_to_p2;
    }
  VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
  if( res2 ){
    goto jump_to_p2;
  }
  }
  break;
}

/* Opcode: ElseNotEq * P2 * * *
/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator.  There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
** OP_Lt or OP_Gt.  Furthermore, the prior OP_Lt or OP_Gt must have the
** OP_Lt or OP_Gt. 
** SQLITE_STOREP2 bit set in the P5 field.
**
** If result of an OP_Eq comparison on the same two operands as the
** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
** jump to P2.  If the result of an OP_Eq comparison on the two previous
** operands would have been true (1), then fall through.
** prior OP_Lt or OP_Gt would have been true, then jump to P2.
** If the result of an OP_Eq comparison on the two previous
** operands would have been false or NULL, then fall through.
*/
case OP_ElseNotEq: {       /* same as TK_ESCAPE, jump */
case OP_ElseEq: {       /* same as TK_ESCAPE, jump */

#ifdef SQLITE_DEBUG
  /* Verify the preconditions of this opcode - that it follows an OP_Lt or
  ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
  ** OP_ReleaseReg opcodes */
  ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
  int iAddr;
  for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
    if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
    assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
    assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
    break;
  }
#endif /* SQLITE_DEBUG */
  VdbeBranchTaken(iCompare!=0, 2);
  if( iCompare!=0 ) goto jump_to_p2;
  VdbeBranchTaken(iCompare==0, 2);
  if( iCompare==0 ) goto jump_to_p2;
  break;
}


/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next
2494
2495
2496
2497
2498
2499
2500


















2501
2502
2503
2504
2505
2506
2507
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  pIn1 = &aMem[pOp->p1];
  VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
  if( (pIn1->flags & MEM_Null)!=0 ){
    goto jump_to_p2;
  }
  break;
}

/* Opcode: ZeroOrNull P1 P2 P3 * *
** Synopsis: r[P2] = 0 OR NULL
**
** If all both registers P1 and P3 are NOT NULL, then store a zero in
** register P2.  If either registers P1 or P3 are NULL then put
** a NULL in register P2.
*/
case OP_ZeroOrNull: {            /* in1, in2, out2, in3 */
  if( (aMem[pOp->p1].flags & MEM_Null)!=0
   || (aMem[pOp->p3].flags & MEM_Null)!=0
  ){
    sqlite3VdbeMemSetNull(aMem + pOp->p2);
  }else{
    sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
  }
  break;
}

/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.  
*/
case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
4551
4552
4553
4554
4555
4556
4557





4558
4559





4560
4561
4562
4563
4564
4565
4566
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561







+
+
+
+
+


+
+
+
+
+







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
4667
4668
4669
4670
4671
4672
4673





4674
4675
4676
4677
4678
4679
4680
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680







+
+
+
+
+







** 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 */
5096
5097
5098
5099
5100
5101
5102
5103

5104
5105
5106
5107
5108
5109
5110
5096
5097
5098
5099
5100
5101
5102

5103
5104
5105
5106
5107
5108
5109
5110







-
+







    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);
      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;
5256
5257
5258
5259
5260
5261
5262
5263

5264
5265
5266
5267
5268
5269
5270
5256
5257
5258
5259
5260
5261
5262

5263
5264
5265
5266
5267
5268
5269
5270







-
+







    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
        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 );
6325
6326
6327
6328
6329
6330
6331
6332

6333
6334
6335
6336
6337
6338
6339
6325
6326
6327
6328
6329
6330
6331

6332
6333
6334
6335
6336
6337
6338
6339







-
+







  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) );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) || db->mallocFailed );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
    db->mDbFlags |= DBFLAG_SchemaChange;
Changes to src/vdbeInt.h.
468
469
470
471
472
473
474

475
476
477
478
479
480
481
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482







+







  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 */
};

556
557
558
559
560
561
562
563


564
565
566
567
568
569
570
557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572







-
+
+







#ifdef SQLITE_DEBUG
int sqlite3VdbeFrameIsValid(VdbeFrame*);
#endif
void sqlite3VdbeFrameMemDel(void*);      /* Destructor on Mem */
void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
void sqlite3VdbePreUpdateHook(
    Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
int sqlite3VdbeTransferError(Vdbe *p);

int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
Changes to src/vdbeapi.c.
1900
1901
1902
1903
1904
1905
1906











1907
1908
1909
1910
1911
1912
1913
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924







+
+
+
+
+
+
+
+
+
+
+







** or SET DEFAULT action is considered a trigger.
*/
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. 
*/
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.
*/
int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
Changes to src/vdbeaux.c.
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503
1485
1486
1487
1488
1489
1490
1491




1492

1493
1494
1495
1496
1497
1498
1499







-
-
-
-
+
-







  zOpName = sqlite3OpcodeName(pOp->opcode);
  nOpName = sqlite3Strlen30(zOpName);
  if( zOpName[nOpName+1] ){
    int seenCom = 0;
    char c;
    zSynopsis = zOpName += nOpName + 1;
    if( strncmp(zSynopsis,"IF ",3)==0 ){
      if( pOp->p5 & SQLITE_STOREP2 ){
        sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
      }else{
        sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
      sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
      }
      zSynopsis = zAlt;
    }
    for(ii=0; (c = zSynopsis[ii])!=0; ii++){
      if( c=='P' ){
        c = zSynopsis[++ii];
        if( c=='4' ){
          sqlite3_str_appendall(&x, zP4);
5191
5192
5193
5194
5195
5196
5197
5198


5199
5200
5201
5202
5203
5204
5205
5187
5188
5189
5190
5191
5192
5193

5194
5195
5196
5197
5198
5199
5200
5201
5202







-
+
+







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 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;

5227
5228
5229
5230
5231
5232
5233

5234
5235
5236
5237
5238
5239
5240
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238







+







  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);
Changes to src/vdbeblob.c.
422
423
424
425
426
427
428
429

430
431
432
433
434
435
436
422
423
424
425
426
427
428

429
430
431
432
433
434
435
436







-
+







      ** 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
          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 ){
493
494
495
496
497
498
499

500
501
502
503
504
505
506
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507







+







  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 );
  }
Changes to src/vtab.c.
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269







+







    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);
Changes to src/wal.c.
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018


1019
1020
1021
1022
1023
1024
1025
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015


1016
1017
1018
1019
1020
1021
1022
1023
1024







-














-
-
+
+







** 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[] */
  int rc;                         /* Return code form walHashGet() */

  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)] );
  rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
  if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */
  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++){
Changes to src/walker.c.
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43

44
45
46
47
48
49
50
28
29
30
31
32
33
34





35

36
37

38
39
40
41
42
43
44
45







-
-
-
-
-

-
+

-
+







    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;

    /* The next two are purely for calls to sqlite3RenameExprUnmap()
    ** within sqlite3WindowOffsetExpr().  Because of constraints imposed
    ** by sqlite3WindowOffsetExpr(), they can never fail.  The results do
    ** not matter anyhow. */
    rc = sqlite3WalkExpr(pWalker, pWin->pStart);
    if( NEVER(rc) ) return WRC_Abort;
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
    if( NEVER(rc) ) return WRC_Abort;
    if( rc ) return WRC_Abort;
    if( bOneOnly ) break;
  }
  return WRC_Continue;
}
#endif

/*
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
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







+
+
+
+
+
+
+
+
+
+














-
+
-
-
-
+
+
+
+
+







  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.
*/
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.
*/
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) && !defined(SQLITE_OMIT_ALTERTABLE)
#if !defined(SQLITE_OMIT_WINDOWFUNC)
  {
    Parse *pParse = pWalker->pParse;
    if( pParse && IN_RENAME_OBJECT ){
  if( p->pWinDefn ){
    Parse *pParse;
    if( pWalker->xSelectCallback2==sqlite3WalkWinDefnDummyCallback
     || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
    ){
      /* 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
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
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







-
+












-
+







*/
int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
  SrcList *pSrc;
  int i;
  SrcItem *pItem;

  pSrc = p->pSrc;
  if( 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)
      ){
        return WRC_Abort;
      }
    }
  }
  return WRC_Continue;
} 
}

/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
** on the compound select chain, p->pPrior. 
**
** If it is not NULL, the xSelectCallback() callback is invoked before
Changes to src/where.c.
257
258
259
260
261
262
263
264



265
266
267
268
269
270
271
257
258
259
260
261
262
263

264
265
266
267
268
269
270
271
272
273







-
+
+
+








/*
** 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 ) return p;
  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.
332
333
334
335
336
337
338












339
340
341
342
343
344
345
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359







+
+
+
+
+
+
+
+
+
+
+
+







             && 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 );
488
489
490
491
492
493
494
495

496
497
498
499
500
501
502
502
503
504
505
506
507
508

509
510
511
512
513
514
515
516







-
+







){
  int i;
  const char *zColl = pIdx->azColl[iCol];

  for(i=0; i<pList->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
    if( ALWAYS(p!=0)
     && p->op==TK_COLUMN
     && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
      if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
        return i;
      }
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
583
584
567
568
569
570
571
572
573
574

575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600







+
-
+

















+







  /* If any of the expressions is an IPK column on table iBase, then return 
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
  ** current SELECT is a correlated sub-query.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
    if( NEVER(p==0) ) continue;
    if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
    if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
    if( p->iTable==iBase && p->iColumn<0 ) return 1;
  }

  /* Loop through all indices on the table, checking each to see if it makes
  ** the DISTINCT qualifier redundant. It does so if:
  **
  **   1. The index is itself UNIQUE, and
  **
  **   2. All of the columns in the index are either part of the pDistinct
  **      list, or else the WHERE clause contains a term of the form "col=X",
  **      where X is a constant value. The collation sequences of the
  **      comparison and select-list expressions must match those of the index.
  **
  **   3. All of those index columns for which the WHERE clause does not
  **      contain a "col=X" term are subject to a NOT NULL constraint.
  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( !IsUniqueIndex(pIdx) ) continue;
    if( pIdx->pPartIdxWhere ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
        if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
        if( indexColumnNotNull(pIdx, i)==0 ) break;
      }
    }
    if( i==pIdx->nKeyCol ){
625
626
627
628
629
630
631
632
633
634


635


636
637
638
639

640
641
642
643
644
645
646
641
642
643
644
645
646
647



648
649

650
651
652

653
654
655
656
657
658
659
660
661
662







-
-
-
+
+
-
+
+

-


+







    if( pOp->p1!=iTabCur ) continue;
    if( pOp->opcode==OP_Column ){
      pOp->opcode = OP_Copy;
      pOp->p1 = pOp->p2 + iRegister;
      pOp->p2 = pOp->p3;
      pOp->p3 = 0;
    }else if( pOp->opcode==OP_Rowid ){
      if( iAutoidxCur ){
        pOp->opcode = OP_Sequence;
        pOp->p1 = iAutoidxCur;
      pOp->opcode = OP_Sequence;
      pOp->p1 = iAutoidxCur;
      }else{
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
      if( iAutoidxCur==0 ){
        pOp->opcode = OP_Null;
        pOp->p1 = 0;
        pOp->p3 = 0;
      }
#endif
    }
  }
}

/*
** Two routines for printing the content of an sqlite3_index_info
** structure.  Used for testing and debugging only.  If neither
797
798
799
800
801
802
803
804

805
806
807
808
809
810
811
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827







-
+







          goto end_auto_index_create;
        }
        pLoop->aLTerm[nKeyCol++] = pTerm;
        idxCols |= cMask;
      }
    }
  }
  assert( nKeyCol>0 );
  assert( nKeyCol>0 || pParse->db->mallocFailed );
  pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
  pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
                     | WHERE_AUTO_INDEX;

  /* Count the number of additional columns needed to create a
  ** covering index.  A "covering index" is an index that contains all
  ** columns that are needed by the query.  With a covering index, the
1934
1935
1936
1937
1938
1939
1940
1941

1942
1943
1944
1945
1946
1947
1948
1950
1951
1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962
1963
1964







-
+








/*
** 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->u, 0, sizeof(pTo->u));
    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 ){
1976
1977
1978
1979
1980
1981
1982











1983
1984
1985
1986
1987
1988
1989
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016







+
+
+
+
+
+
+
+
+
+
+







    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
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656







+







         || (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(
3589
3590
3591
3592
3593
3594
3595
3596



3597
3598
3599
3600
3601
3602
3603
3617
3618
3619
3620
3621
3622
3623

3624
3625
3626
3627
3628
3629
3630
3631
3632
3633







-
+
+
+







#endif
        {
          rc = whereLoopAddBtree(&sSubBuild, mPrereq);
        }
        if( rc==SQLITE_OK ){
          rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
        }
        assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
        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;
3818
3819
3820
3821
3822
3823
3824
3825

3826
3827
3828
3829
3830
3831
3832
3848
3849
3850
3851
3852
3853
3854

3855
3856
3857
3858
3859
3860
3861
3862







-
+







    ** clause of the form X IS NULL or X=? that reference only outer
    ** loops.
    */
    for(i=0; i<nOrderBy; i++){
      if( MASKBIT(i) & obSat ) continue;
      pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
      if( NEVER(pOBExpr==0) ) continue;
      if( pOBExpr->op!=TK_COLUMN ) continue;
      if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
      if( pOBExpr->iTable!=iCur ) continue;
      pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
                       ~ready, eqOpMask, 0);
      if( pTerm==0 ) continue;
      if( pTerm->eOperator==WO_IN ){
        /* IN terms are only valid for sorting in the ORDER BY LIMIT 
        ** optimization, and then only if they are actually used
3858
3859
3860
3861
3862
3863
3864




3865
3866
3867
3868
3869
3870
3871
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905







+
+
+
+







        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.
      */
3925
3926
3927
3928
3929
3930
3931
3932

3933
3934
3935
3936
3937
3938
3939
3940











3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954

3955
3956
3957
3958
3959
3960
3961
3959
3960
3961
3962
3963
3964
3965

3966
3967







3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991

3992
3993
3994
3995
3996
3997
3998
3999







-
+

-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+













-
+







          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
        ** WhereLoop is not well-ordered.  tag-20210426-1
        */
        if( isOrderDistinct
         && iColumn>=0
         && j>=pLoop->u.btree.nEq
         && pIndex->pTable->aCol[iColumn].notNull==0
        ){
          isOrderDistinct = 0;
        }
        if( isOrderDistinct ){
          if( iColumn>=0
           && j>=pLoop->u.btree.nEq
           && pIndex->pTable->aCol[iColumn].notNull==0
          ){
            isOrderDistinct = 0;
          }
          if( iColumn==XN_EXPR ){
            isOrderDistinct = 0;
          }
        } 

        /* Find the ORDER BY term that corresponds to the j-th column
        ** of the index and mark that ORDER BY term off 
        */
        isMatch = 0;
        for(i=0; bOnce && i<nOrderBy; i++){
          if( MASKBIT(i) & obSat ) continue;
          pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
          testcase( wctrlFlags & WHERE_GROUPBY );
          testcase( wctrlFlags & WHERE_DISTINCTBY );
          if( NEVER(pOBExpr==0) ) continue;
          if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
          if( iColumn>=XN_ROWID ){
            if( pOBExpr->op!=TK_COLUMN ) continue;
            if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
            if( pOBExpr->iTable!=iCur ) continue;
            if( pOBExpr->iColumn!=iColumn ) continue;
          }else{
            Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
            if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
              continue;
            }
4116
4117
4118
4119
4120
4121
4122
4123

4124
4125
4126
4127
4128
4129
4130
4154
4155
4156
4157
4158
4159
4160

4161
4162
4163
4164
4165
4166
4167
4168







-
+







  ** 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) );
    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
5048
5049
5050
5051
5052
5053
5054
5055


5056
5057
5058
5059
5060
5061
5062
5086
5087
5088
5089
5090
5091
5092

5093
5094
5095
5096
5097
5098
5099
5100
5101







-
+
+







  **
  **     SELECT DISTINCT v1, v3 FROM t1 
  **       LEFT JOIN t2
  **       LEFT JOIN t3 ON (t1.ipk=t3.ipk)
  */
  notReady = ~(Bitmask)0;
  if( pWInfo->nLevel>=2
   && pResultSet!=0               /* guarantees condition (1) above */
   && pResultSet!=0                         /* these two combine to guarantee */
   && 0==(wctrlFlags & WHERE_AGG_DISTINCT)  /* condition (1) above */
   && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
  ){
    int i;
    Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
    if( sWLB.pOrderBy ){
      tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
    }
5307
5308
5309
5310
5311
5312
5313


5314
5315
5316
5317
5318
5319
5320
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361







+
+







  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;
}

/*
5403
5404
5405
5406
5407
5408
5409


5410
5411
5412
5413
5414
5415
5416
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459







+
+







      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 ){
5427
5428
5429
5430
5431
5432
5433





5434
5435
5436
5437
5438
5439
5440
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488







+
+
+
+
+







              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);
        }
5561
5562
5563
5564
5565
5566
5567
5568

5569
5570
5571
5572
5573
5574
5575
5609
5610
5611
5612
5613
5614
5615

5616
5617
5618
5619
5620
5621
5622
5623







-
+







      pOp = sqlite3VdbeGetOp(v, k - 1);
      assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_Rowid  || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
      pOp = sqlite3VdbeGetOp(v, k);
      pLastOp = pOp + (last - k);
      assert( pOp<pLastOp || (pParse->nErr>0 && pOp==pLastOp) );
      assert( pOp<=pLastOp );
      do{
        if( pOp->p1!=pLevel->iTabCur ){
          /* no-op */
        }else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
         || pOp->opcode==OP_Offset
#endif
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622

5623
5624
5625
5626
5654
5655
5656
5657
5658
5659
5660








5661
5662
5663
5664
5665
5666
5667







-
-
-
-
-
-
-
-


+




      }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
    }
  }

  /* Undo all Expr node modifications */
  while( pWInfo->pExprMods ){
    WhereExprMod *p = pWInfo->pExprMods;
    pWInfo->pExprMods = p->pNext;
    memcpy(p->pExpr, &p->orig, sizeof(p->orig));
    sqlite3DbFree(db, p);
  }

  /* Final cleanup
  */
  if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
  pParse->nQueryLoop = pWInfo->savedNQueryLoop;
  whereInfoFree(db, pWInfo);
  return;
}
Changes to src/whereInt.h.
289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304
289
290
291
292
293
294
295


296
297
298
299
300
301
302
303
304







-
-
+
+







*/
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 aEquiv[] */
  unsigned char iEquiv;      /* Next unused slot in aEquiv[] */
  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 */
};

/*
599
600
601
602
603
604
605

606
607
599
600
601
602
603
604
605
606
607
608







+


#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) */
Changes to src/wherecode.c.
144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159

160
161
162
163
164
165
166
167
144
145
146
147
148
149
150







151


152

153
154
155
156
157
158
159







-
-
-
-
-
-
-
+
-
-
+
-







    if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;

    isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
            || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
            || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));

    sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
    sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
    if( pItem->pSelect ){
      sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId);
    }else{
      sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
    }

    str.printfFlags = SQLITE_PRINTF_INTERNAL;
    if( pItem->zAlias ){
      sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
    sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
    }
    if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
      const char *zFmt = 0;
      Index *pIdx;

      assert( pLoop->u.btree.pIndex!=0 );
      pIdx = pLoop->u.btree.pIndex;
      assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
301
302
303
304
305
306
307






308
309
310
311
312
313
314
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312







+
+
+
+
+
+







      && (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++;
  }
618
619
620
621
622
623
624













625



626
627
628
629
630
631
632
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645







+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+







      }
    }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);
    disableTerm(pLevel, pTerm);
  }

  return iReg;
}

/*
** Generate code that will evaluate all == and IN constraints for an
** index scan.
**
704
705
706
707
708
709
710

711
712
713
714
715
716
717
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731







+







  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);
755
756
757
758
759
760
761
762

763
764
765
766
767
768
769
769
770
771
772
773
774
775

776
777
778
779
780
781
782
783







-
+







      }
    }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( zAff ){
      if( pParse->db->mallocFailed==0 ){
        if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
          zAff[j] = SQLITE_AFF_BLOB;
        }
        if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
          zAff[j] = SQLITE_AFF_BLOB;
        }
      }
2452
2453
2454
2455
2456
2457
2458

2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480







+







    testcase( pAlt->eOperator & WO_EQ );
    testcase( pAlt->eOperator & WO_IS );
    testcase( pAlt->eOperator & WO_IN );
    VdbeModuleComment((v, "begin transitive constraint"));
    sEAlt = *pAlt->pExpr;
    sEAlt.pLeft = pE->pLeft;
    sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
    pAlt->wtFlags |= TERM_CODED;
  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
Changes to src/whereexpr.c.
507
508
509
510
511
512
513

514
515
516
517
518
519
520
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521







+







){
  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;
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
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
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
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
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
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
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
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1004
1005
1006
1007
1008
1009
1010













































































































































































































































































1011
1012
1013
1014
1015
1016
1017







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







    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);
}

/*
** Expression callback for exprUsesSrclist().
*/
static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
  if( pExpr->op==TK_COLUMN ){
    SrcList *pSrc = p->u.pSrcList;
    int iCsr = pExpr->iTable;
    int ii;
    for(ii=0; ii<pSrc->nSrc; ii++){
      if( pSrc->a[ii].iCursor==iCsr ){
        return p->eCode ? WRC_Abort : WRC_Continue;
      }
    }
    return p->eCode ? WRC_Continue : WRC_Abort;
  }
  return WRC_Continue;
}

/*
** Select callback for exprUsesSrclist().
*/
static int exprUsesSrclistSelectCb(Walker *NotUsed1, Select *NotUsed2){
  UNUSED_PARAMETER(NotUsed1);
  UNUSED_PARAMETER(NotUsed2);
  return WRC_Abort;
}

/*
** This function always returns true if expression pExpr contains
** a sub-select.
**
** If there is no sub-select in pExpr, then return true if pExpr
** contains a TK_COLUMN node for a table that is (bUses==1)
** or is not (bUses==0) in pSrc.
**
** Said another way:
**
**   bUses      Return     Meaning
**   --------   ------     ------------------------------------------------
**
**   bUses==1   true       pExpr contains either a sub-select or a
**                         TK_COLUMN referencing pSrc.
**
**   bUses==1   false      pExpr contains no sub-selects and all TK_COLUMN
**                         nodes reference tables not found in pSrc
**
**   bUses==0   true       pExpr contains either a sub-select or a TK_COLUMN
**                         that references a table not in pSrc.
**
**   bUses==0   false      pExpr contains no sub-selects and all TK_COLUMN
**                         nodes reference pSrc
*/
static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
  Walker sWalker;
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.eCode = bUses;
  sWalker.u.pSrcList = pSrc;
  sWalker.xExprCallback = exprUsesSrclistCb;
  sWalker.xSelectCallback = exprUsesSrclistSelectCb;
  return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
}

/*
** Context object used by exprExistsToInIter() as it iterates through an
** expression tree.
*/
struct ExistsToInCtx {
  SrcList *pSrc;    /* The tables in an EXISTS(SELECT ... FROM <here> ...) */
  Expr *pInLhs;     /* OUT:  Use this as the LHS of the IN operator */
  Expr *pEq;        /* OUT:  The == term that include pInLhs */
  Expr **ppAnd;     /* OUT:  The AND operator that includes pEq as a child */
  Expr **ppParent;  /* The AND operator currently being examined */
};

/*
** Iterate through all AND connected nodes in the expression tree
** headed by (*ppExpr), populating the structure passed as the first
** argument with the values required by exprAnalyzeExistsFindEq().
**
** This function returns non-zero if the expression tree does not meet
** the two conditions described by the header comment for
** exprAnalyzeExistsFindEq(), or zero if it does.
*/
static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
  Expr *pExpr = *ppExpr;
  switch( pExpr->op ){
    case TK_AND:
      p->ppParent = ppExpr;
      if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
      p->ppParent = ppExpr;
      if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
      break;
    case TK_EQ: {
      int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
      int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
      if( bLeft || bRight ){
        if( (bLeft && bRight) || p->pInLhs ) return 1;
        p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
        if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
        p->pEq = pExpr;
        p->ppAnd = p->ppParent;
      }
      break;
    }
    default:
      if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
        return 1;
      }
      break;
  }

  return 0;
}

/*
** This function is used by exprAnalyzeExists() when creating virtual IN(...)
** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
** clause of the Select object passed as the first argument into one or more
** expressions joined by AND operators, and then tests if the following are
** true:
**
**   1. Exactly one of the AND separated terms refers to the outer
**      query, and it is an == (TK_EQ) expression.
**
**   2. Only one side of the == expression refers to the outer query, and 
**      it does not refer to any columns from the inner query.
**
** If both these conditions are true, then a pointer to the side of the ==
** expression that refers to the outer query is returned. The caller will
** use this expression as the LHS of the IN(...) virtual term. Or, if one
** or both of the above conditions are not true, NULL is returned.
**
** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
** to the == expression node before returning. If pppAnd is non-NULL and
** the == node is not the root of the WHERE clause, then *pppAnd is set
** to point to the pointer to the AND node that is the parent of the ==
** node within the WHERE expression tree.
*/
static Expr *exprAnalyzeExistsFindEq(
  Select *pSel,                   /* The SELECT of the EXISTS */
  Expr **ppEq,                    /* OUT: == node from WHERE clause */
  Expr ***pppAnd                  /* OUT: Pointer to parent of ==, if any */
){
  struct ExistsToInCtx ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.pSrc = pSel->pSrc;
  if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
    return 0;
  }
  if( ppEq ) *ppEq = ctx.pEq;
  if( pppAnd ) *pppAnd = ctx.ppAnd;
  return ctx.pInLhs;
}

/*
** Term idxTerm of the WHERE clause passed as the second argument is an
** EXISTS expression with a correlated SELECT statement on the RHS.
** This function analyzes the SELECT statement, and if possible adds an
** equivalent "? IN(SELECT...)" virtual term to the WHERE clause. 
**
** For an EXISTS term such as the following:
**
**     EXISTS (SELECT ... FROM <srclist> WHERE <e1> = <e2> AND <e3>)
**
** The virtual IN() term added is:
**
**     <e1> IN (SELECT <e2> FROM <srclist> WHERE <e3>)
**
** The virtual term is only added if the following conditions are met:
**
**     1. The sub-select must not be an aggregate or use window functions,
**
**     2. The sub-select must not be a compound SELECT,
**
**     3. Expression <e1> must refer to at least one column from the outer
**        query, and must not refer to any column from the inner query 
**        (i.e. from <srclist>).
**
**     4. <e2> and <e3> must not refer to any values from the outer query.
**        In other words, once <e1> has been removed, the inner query
**        must not be correlated.
**
*/
static void exprAnalyzeExists(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the WHERE clause */
  int idxTerm               /* Index of the term to be analyzed */
){
  Parse *pParse = pWC->pWInfo->pParse;
  WhereTerm *pTerm = &pWC->a[idxTerm];
  Expr *pExpr = pTerm->pExpr;
  Select *pSel = pExpr->x.pSelect;
  Expr *pDup = 0;
  Expr *pEq = 0;
  Expr *pRet = 0;
  Expr *pInLhs = 0;
  Expr **ppAnd = 0;
  int idxNew;
  sqlite3 *db = pParse->db;

  assert( pExpr->op==TK_EXISTS );
  assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );

  if( pSel->selFlags & SF_Aggregate ) return;
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( pSel->pWin ) return;
#endif
  if( pSel->pPrior ) return;
  if( pSel->pWhere==0 ) return;
  if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;

  pDup = sqlite3ExprDup(db, pExpr, 0);
  if( db->mallocFailed ){
    sqlite3ExprDelete(db, pDup);
    return;
  }
  pSel = pDup->x.pSelect;
  sqlite3ExprListDelete(db, pSel->pEList);
  pSel->pEList = 0;

  pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
  assert( pInLhs && pEq );
  assert( pEq==pSel->pWhere || ppAnd );
  if( pInLhs==pEq->pLeft ){
    pRet = pEq->pRight;
  }else{
    CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
    pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
    pRet = pEq->pLeft;
  }

  assert( pDup->pLeft==0 );
  pDup->op = TK_IN;
  pDup->pLeft = pInLhs;
  pDup->flags &= ~EP_VarSelect;
  if( pRet->op==TK_VECTOR ){
    pSel->pEList = pRet->x.pList;
    pRet->x.pList = 0;
    sqlite3ExprDelete(db, pRet);
  }else{
    pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
  }
  pEq->pLeft = 0;
  pEq->pRight = 0;
  if( ppAnd ){
    Expr *pAnd = *ppAnd;
    Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
    pAnd->pLeft = pAnd->pRight = 0;
    sqlite3ExprDelete(db, pAnd);
    *ppAnd = pOther;
  }else{
    assert( pSel->pWhere==pEq );
    pSel->pWhere = 0;
  }
  sqlite3ExprDelete(db, pEq);

#ifdef WHERETRACE_ENABLED  /* 0x20 */
  if( sqlite3WhereTrace & 0x20 ){
    sqlite3DebugPrintf("Convert EXISTS:\n");
    sqlite3TreeViewExpr(0, pExpr, 0);
    sqlite3DebugPrintf("into IN:\n");
    sqlite3TreeViewExpr(0, pDup, 0);
  }
#endif
  idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
  exprAnalyze(pSrc, pWC, idxNew);
  markTermAsChild(pWC, idxNew, idxTerm);
  pWC->a[idxTerm].wtFlags |= TERM_COPIED;
}

/*
** 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.
**
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1195
1196
1197
1198
1199
1200
1201










1202
1203
1204
1205
1206
1207
1208







-
-
-
-
-
-
-
-
-
-







  */
  else if( pExpr->op==TK_OR ){
    assert( pWC->op==TK_AND );
    exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
    pTerm = &pWC->a[idxTerm];
  }
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */

  else if( pExpr->op==TK_EXISTS ){
    /* Perhaps treat an EXISTS operator as an IN operator */
    if( (pExpr->flags & EP_VarSelect)!=0
     && OptimizationEnabled(db, SQLITE_ExistsToIN)
    ){
      exprAnalyzeExists(pSrc, pWC, idxTerm);
    }
  }

  /* 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 ){
Changes to src/window.c.
784
785
786
787
788
789
790

791
792
793
794
795
796
797
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798







+







        }
      }
      /* no break */ deliberate_fall_through

    case TK_AGG_FUNCTION:
    case TK_COLUMN: {
      int iCol = -1;
      if( pParse->db->mallocFailed ) return WRC_Abort;
      if( p->pSub ){
        int i;
        for(i=0; i<p->pSub->nExpr; i++){
          if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
            iCol = i;
            break;
          }
893
894
895
896
897
898
899

900

901




902

903
904
905
906
907
908
909
894
895
896
897
898
899
900
901

902
903
904
905
906
907

908
909
910
911
912
913
914
915







+
-
+

+
+
+
+
-
+







  ExprList *pAppend,      /* List of values to append. Might be NULL */
  int bIntToNull
){
  if( pAppend ){
    int i;
    int nInit = pList ? pList->nExpr : 0;
    for(i=0; i<pAppend->nExpr; i++){
      sqlite3 *db = pParse->db;
      Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
      Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
      assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
      if( db->mallocFailed ){
        sqlite3ExprDelete(db, pDup);
        break;
      }
      if( bIntToNull && pDup ){
      if( bIntToNull ){
        int iDummy;
        Expr *pSub;
        for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
          assert( pSub );
        }
        if( sqlite3ExprIsInteger(pSub, &iDummy) ){
          pSub->op = TK_NULL;
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485







+







    VdbeCoverage(v);
    assert( eCond==0 || eCond==1 || eCond==2 );
    VdbeCoverageIf(v, eCond==0);
    VdbeCoverageIf(v, eCond==1);
    VdbeCoverageIf(v, eCond==2);
  }
  sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
  sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
  VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
  VdbeCoverageNeverNullIf(v, eCond==1); /*   the OP_MustBeInt */
  VdbeCoverageNeverNullIf(v, eCond==2);
  VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */
  VdbeCoverageNeverNullIf(v, eCond==4); /*   the OP_Ge */
  sqlite3MayAbort(pParse);
  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580







+







  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;
};

/*
1675
1676
1677
1678
1679
1680
1681
1682
1683


1684
1685
1686
1687
1688
1689
1690


1691
1692
1693
1694
1695
1696
1697
1683
1684
1685
1686
1687
1688
1689


1690
1691
1692
1693
1694
1695
1696


1697
1698
1699
1700
1701
1702
1703
1704
1705







-
-
+
+





-
-
+
+







        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
        addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
        VdbeCoverage(v);
        sqlite3ReleaseTempReg(pParse, regTmp);
      }
      
      if( pWin->bExprArgs ){
        int iStart = sqlite3VdbeCurrentAddr(v);
        VdbeOp *pOp, *pEnd;
        int iOp = sqlite3VdbeCurrentAddr(v);
        int iEnd;

        nArg = pWin->pOwner->x.pList->nExpr;
        regArg = sqlite3GetTempRange(pParse, nArg);
        sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);

        pEnd = sqlite3VdbeGetOp(v, -1);
        for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
        for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
          VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
          if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
            pOp->p1 = csr;
          }
        }
      }
      if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        CollSeq *pColl;
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
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
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
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093




2094
2095
2096
2097
2098



















2099
2100
2101
2102
2103
2104
2105







-
+


















+

+
+
+
+












-
-
-
-





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
**   if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition addition
** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
  WindowCodeArg *p, 
  int op,                         /* OP_Ge, OP_Gt, or OP_Le */
  int csr1,                       /* Cursor number for cursor 1 */
  int regVal,                     /* Register containing non-negative number */
  int csr2,                       /* Cursor number for cursor 2 */
  int lbl                         /* Jump destination if condition is true */
){
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  ExprList *pOrderBy = p->pMWin->pOrderBy;  /* ORDER BY clause for window */
  int reg1 = sqlite3GetTempReg(pParse);     /* Reg. for csr1.peerVal+regVal */
  int reg2 = sqlite3GetTempReg(pParse);     /* Reg. for csr2.peerVal */
  int regString = ++pParse->nMem;           /* Reg. for constant value '' */
  int arith = OP_Add;                       /* OP_Add or OP_Subtract */
  int addrGe;                               /* Jump destination */
  int addrDone = sqlite3VdbeMakeLabel(pParse);   /* Address past OP_Ge */
  CollSeq *pColl;

  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
  assert( pOrderBy && pOrderBy->nExpr==1 );
  if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
    switch( op ){
      case OP_Ge: op = OP_Le; break;
      case OP_Gt: op = OP_Lt; break;
      default: assert( op==OP_Le ); op = OP_Ge; break;
    }
    arith = OP_Subtract;
  }

  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
      reg1, (arith==OP_Add ? "+" : "-"), regVal,
      ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
  ));

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  ** This block adds (or subtracts for DESC) the numeric value in regVal
  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
  **   if( reg1>='' ) goto addrGe;
  **   reg1 = reg1 +/- regVal
  **   addrGe:
  **
  ** Since all strings and blobs are greater-than-or-equal-to an empty string,
  ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
  ** then the arithmetic is performed, but since adding or subtracting from
  ** NULL is always NULL anyway, this case is handled as required too.  */
  sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
  sqlite3VdbeJumpHere(v, addrGe);

  /* If the BIGNULL flag is set for the ORDER BY, then it is required to 
  ** consider NULL values to be larger than all other values, instead of 
  ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
  ** (and adding that capability causes a performance regression), so
  ** instead if the BIGNULL flag is set then cases where either reg1 or
  ** reg2 are NULL are handled separately in the following block. The code
  ** generated is equivalent to:
2138
2139
2140
2141
2142
2143
2144
2145

2146
2147
2148
2149
2150
2151

2152
2153






















2154
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164
2165
2166
2167
2168
2128
2129
2130
2131
2132
2133
2134

2135
2136
2137
2138
2139
2140

2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181







-
+





-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








+







        break;
      case OP_Le: 
        sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); 
        VdbeCoverage(v); 
        break;
      default: assert( op==OP_Lt ); /* no-op */ break;
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);

    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
    if( op==OP_Gt || op==OP_Ge ){
      sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
      sqlite3VdbeChangeP2(v, -1, addrDone);
    }
  }

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  ** This block adds (or subtracts for DESC) the numeric value in regVal
  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
  **   if( reg1>='' ) goto addrGe;
  **   reg1 = reg1 +/- regVal
  **   addrGe:
  **
  ** Since all strings and blobs are greater-than-or-equal-to an empty string,
  ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
  ** then the arithmetic is performed, but since adding or subtracting from
  ** NULL is always NULL anyway, this case is handled as required too.  */
  sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
  VdbeCoverage(v);
  if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
    sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  }
  sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
  sqlite3VdbeJumpHere(v, addrGe);

  /* Compare registers reg2 and reg1, taking the jump if required. Note that
  ** control skips over this test if the BIGNULL flag is set and either
  ** reg1 or reg2 contain a NULL value.  */
  sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
  sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
  sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
  sqlite3VdbeResolveLabel(v, addrDone);

  assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
  testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
  testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
  testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
  testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
  sqlite3ReleaseTempReg(pParse, reg1);
2230
2231
2232
2233
2234
2235
2236
2237



2238
2239

2240
2241
2242

2243
2244
2245
2246









2247
2248
2249
2250
2251
2252
2253
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







-
+
+
+

-
+



+
-
-
-
-
+
+
+
+
+
+
+
+
+







    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).  */
  ** 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 && op==WINDOW_AGGINVERSE
   && 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);
      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:
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2757
2758
2759
2760
2761
2762
2763

2764
2765
2766
2767
2768
2769
2770







-







  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 regRowid;                   /* Rowid for regRecord in eph table */
  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 */
2808
2809
2810
2811
2812
2813
2814
2815

2816
2817
2818
2819
2820
2821
2822
2828
2829
2830
2831
2832
2833
2834

2835
2836
2837
2838
2839
2840
2841
2842







-
+








  /* 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;
  regRowid = ++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;
  }
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873



2874
2875
2876
2877
2878
2879
2880
2884
2885
2886
2887
2888
2889
2890



2891
2892
2893
2894
2895
2896
2897
2898
2899
2900







-
-
-
+
+
+







    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, regRowid);
  sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
  addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
  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);
2984
2985
2986
2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018







+








  /* 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);
Changes to test/alter4.test.
314
315
316
317
318
319
320
321

322
323

324
325
326
327
328

329
330

331
332
333
334
335
336
337
314
315
316
317
318
319
320

321
322

323
324
325
326
327

328
329

330
331
332
333
334
335
336
337







-
+

-
+




-
+

-
+







        INSERT INTO log VALUES('a', new.a, new.b);
      END;
      CREATE TEMP TRIGGER t1_b AFTER INSERT ON t1 BEGIN
        INSERT INTO log VALUES('b', new.a, new.b);
      END;
  
      INSERT INTO t1 VALUES(1, 2);
      SELECT * FROM log;
      SELECT * FROM log ORDER BY trig, a, b;
    }
  } {b 1 2 a 1 2}
  } {a 1 2 b 1 2}
  do_test alter4-6.2 {
    execsql {
      ALTER TABLE t1 ADD COLUMN c DEFAULT 'c';
      INSERT INTO t1(a, b) VALUES(3, 4);
      SELECT * FROM log;
      SELECT * FROM log ORDER BY trig, a, b;
    }
  } {b 1 2 a 1 2 b 3 4 a 3 4}
  } {a 1 2 a 3 4 b 1 2 b 3 4}
}

# Ticket #1183 - Make sure adding columns to large tables does not cause
# memory corruption (as was the case before this bug was fixed).
do_test alter4-8.1 {
  execsql {
    CREATE TEMP TABLE t4(c1);
Changes to test/alterauth2.test.
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
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







+


















+










+




do_auth_test 1.2 {
  ALTER TABLE t2 RENAME a TO aaa;
} {
  {SQLITE_ALTER_TABLE main t2 {} {}} 
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_column {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}} 
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

do_auth_test 1.3 {
  ALTER TABLE t2 DROP COLUMN c;
} {
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_drop_column {} {}}
  {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}}
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

finish_test
Changes to test/altercol.test.
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
563
564
565
566
567
568
569

570
571
572
573
574
575
576
577







-
+








do_execsql_test 13.1.6 {
  UPDATE sqlite_master SET sql = '' WHERE name='x1i';
} {}

do_catchsql_test 13.1.7 {
  ALTER TABLE x1 RENAME COLUMN t TO ttt;
} {1 {database disk image is malformed}}
} {1 {error in index x1i: }}

do_execsql_test 13.1.8 {
  DELETE FROM sqlite_master WHERE name = 'x1i';
}

do_execsql_test 13.2.0 {
  CREATE TABLE data(x UNIQUE, y, z);
830
831
832
833
834
835
836
837

838
























839
830
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863








+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  CREATE TABLE t2(c, othername, extra AS (c + 1));
  ALTER TABLE t1 RENAME a to othername;
  SELECT sql FROM sqlite_schema;
} {
  {CREATE TABLE t1(othername, b)}
  {CREATE TABLE t2(c, othername, extra AS (c + 1))}
}

#-------------------------------------------------------------------------

#
reset_db
do_execsql_test 22.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX x1 on t1("c"=b);
  INSERT INTO t1 VALUES('a', 'a');
  INSERT INTO t1 VALUES('b', 'b');
  INSERT INTO t1 VALUES('c', 'c');
  ALTER TABLE t1 RENAME COLUMN a TO "c";
  PRAGMA integrity_check;
} {ok}

reset_db
do_execsql_test 23.0 {
  CREATE TABLE t1('a'"b",c);
  CREATE INDEX i1 ON t1('a');
  INSERT INTO t1 VALUES(1,2), (3,4);
  ALTER TABLE t1 RENAME COLUMN a TO x;
  PRAGMA integrity_check;
  SELECT sql FROM sqlite_schema WHERE name='t1';

} {ok {CREATE TABLE t1("x" "b",c)}}


finish_test
Changes to test/alterdropcol.test.
271
272
273
274
275
276
277




























































278
279
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  CREATE TABLE t2(x,y,z);
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET sql='CREATE VIEW t2(x,y,z) AS SELECT b,a,c FROM t1'
   WHERE name='t2';
  PRAGMA writable_schema=OFF;
  ALTER TABLE t2 DROP COLUMN z;
} {1 {database disk image is malformed}}

# 2021-04-06 dbsqlfuzz crash-331c5c29bb76257b198f1318eef3288f9624c8ce
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a, b, c, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
}
do_execsql_test 7.1 {
  ALTER TABLE t1 DROP COLUMN c;                
}
do_execsql_test 7.2 {
  SELECT sql FROM sqlite_schema;
} {{CREATE TABLE t1(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID}}
do_execsql_test 7.3 {
  SELECT * FROM t1;
} {1 2 4 5}

reset_db
do_execsql_test 8.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema 
  SET sql = 'CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b)'
}
db close
sqlite3 db test.db
do_execsql_test 8.1 {
  ALTER TABLE t1 DROP COLUMN b;                
}
do_execsql_test 8.2 {
  SELECT sql FROM sqlite_schema;
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT)}}

#-------------------------------------------------------------------------

foreach {tn wo} {
  1 {}
  2 {WITHOUT ROWID}
} {
  reset_db
  do_execsql_test 9.$tn.0 "
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) $wo;
  "
  do_execsql_test 9.$tn.1 {
    WITH s(i) AS (
        SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
    )
    INSERT INTO t1(a, b, c) SELECT i, 123, 456 FROM s;
  }
  do_execsql_test 9.$tn.2 {
    ALTER TABLE t1 DROP COLUMN b;
  }

  do_execsql_test 9.$tn.3 {
    SELECT count(*), c FROM t1 GROUP BY c;
  } {50000 456}
}



finish_test
Changes to test/altermalloc3.test.
18
19
20
21
22
23
24








25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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








+
+
+
+
+
+
+
+















-
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE x1(
      one, two, three, PRIMARY KEY(one), 
      CHECK (three!="xyz"), CHECK (two!="one")
  ) WITHOUT ROWID;
  CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
  CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
  END;
  CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3, 4);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { ALTER TABLE t1 DROP COLUMN c }
} -test {
  faultsim_test_result {0 {}}
}


finish_test

Added test/alterqf.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
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 March 16
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. This
# script focuses on testing internal function sqlite_rename_quotefix().
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix alterqf

sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
}

foreach {tn before after} {
  1 {CREATE VIEW v1 AS SELECT "a", "b", "notacolumn!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'notacolumn!', "c" FROM t1}

  2 {CREATE VIEW v1 AS SELECT "a", "b", "not'a'column!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'not''a''column!', "c" FROM t1}

  3 {CREATE VIEW v1 AS SELECT "a", "b", "not""a""column!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'not"a"column!', "c" FROM t1}

  4 {CREATE VIEW v1 AS SELECT "val", count("b") FROM t1 GROUP BY "abc"}
    {CREATE VIEW v1 AS SELECT 'val', count("b") FROM t1 GROUP BY 'abc'}

  5 {CREATE TABLE xyz(a CHECK (a!="str"), b AS (a||"str"))}
    {CREATE TABLE xyz(a CHECK (a!='str'), b AS (a||'str'))}

  6 {CREATE INDEX i1 ON t1(a || "str", "b", "val")}
    {CREATE INDEX i1 ON t1(a || 'str', "b", 'val')}

  7 {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT "abcd"; END}
    {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 'abcd'; END}

  8 {CREATE VIEW v1 AS SELECT "string"'alias' FROM t1}
    {CREATE VIEW v1 AS SELECT 'string' 'alias' FROM t1}

  9 {CREATE INDEX i1 ON t1(a) WHERE "b"="bb"}
    {CREATE INDEX i1 ON t1(a) WHERE "b"='bb'}

 10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))} 
    {CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))} 

 11 {
    CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN 
      SELECT max("str", new."a") FROM t1 
          WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
      UPDATE t1 SET c= b + "str";
      DELETE FROM t1 WHERE EXISTS (
        SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
      );
    END;
 } {
    CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN 
      SELECT max('str', new."a") FROM t1 
          WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
      UPDATE t1 SET c= b + 'str';
      DELETE FROM t1 WHERE EXISTS (
        SELECT 1 FROM t1 AS o WHERE o."a" = 'o.a' AND t1.b IN('t1.b')
      );
    END;
 }

} {
  do_execsql_test 1.$tn {
    SELECT sqlite_rename_quotefix('main', $before)
  } [list $after]
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE x1(
      one, two, three, PRIMARY KEY(one), 
      CHECK (three!="xyz"), CHECK (two!="one")
  ) WITHOUT ROWID;
  CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
  CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
  END;
}

do_execsql_test 2.1 {
  ALTER TABLE x1 RENAME two TO 'four';
  SELECT sql FROM sqlite_schema;
  SELECT sql FROM sqlite_temp_schema;
} {{CREATE TABLE x1(
      one, "four", three, PRIMARY KEY(one), 
      CHECK (three!='xyz'), CHECK ("four"!="one")
  ) WITHOUT ROWID}
  {CREATE INDEX x1i ON x1(one+"four"+'four') WHERE 'five'}
  {CREATE TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET "four"=new.three || 'new' WHERE one=new.one||'';
  END}
}


finish_test
Changes to test/altertab.test.
732
733
734
735
736
737
738

739
740
741
































732
733
734
735
736
737
738
739



740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771







+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
  END;
  CREATE VIEW v1 AS SELECT * FROM nosuchtable;
}
do_catchsql_test 24.2.1 {
  ALTER TABLE t1 RENAME TO t2;
} {1 {error in trigger AFTER: no such table: main.nosuchtable}}

#--------------------------------------------------------------------------

finish_test

#
reset_db
do_execsql_test 25.1 {
  CREATE TABLE xx(x);
  CREATE VIEW v3(b) AS WITH b AS (SELECT b FROM (SELECT * FROM t2)) VALUES(1);
}

ifcapable json1&&vtab {
  do_catchsql_test 25.2 {
    ALTER TABLE json_each RENAME TO t4;
  } {1 {table json_each may not be altered}}
}

# 2021-05-01 dbsqlfuzz bc17a306a09329bba0ecc61547077f6178bcf321
# Remove a NEVER() inserted on 2019-12-09 that is reachable after all.
#
reset_db
do_execsql_test 26.1 {
  CREATE TABLE t1(k,v);
  CREATE TABLE t2_a(k,v);
  CREATE VIEW t2 AS SELECT * FROM t2_a;
  CREATE TRIGGER r2 AFTER INSERT ON t1 BEGIN
    UPDATE t1 
       SET (k,v)=((WITH cte1(a) AS (SELECT 1 FROM t2) SELECT t2.k FROM t2, cte1),1);
  END;
  ALTER TABLE t1 RENAME TO t1x;
  INSERT INTO t2_a VALUES(2,3);
  INSERT INTO t1x VALUES(98,99);
  SELECT * FROM t1x;
} {2 1}

finish_test
Changes to test/analyze3.test.
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
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







-
+


-
+









-
+




-
+




-
+




-
+




-
+








# The first of the following two SELECT statements visits 99 rows. So
# it is better to use the index. But the second visits every row in 
# the table (1000 in total) so it is better to do a full-table scan.
#
do_eqp_test analyze3-1.1.2 {
  SELECT sum(y) FROM t1 WHERE x>200 AND x<300
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
} {SEARCH t1 USING INDEX i1 (x>? AND x<?)}
do_eqp_test analyze3-1.1.3 {
  SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 
} {SCAN TABLE t1}
} {SCAN t1}

# 2017-06-26:  Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
# the use of bound parameters by STAT4
#
db cache flush
unset -nocomplain l
unset -nocomplain u
do_eqp_test analyze3-1.1.3.100 {
  SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
} {SEARCH t1 USING INDEX i1 (x>? AND x<?)}
set l 200
set u 300
do_eqp_test analyze3-1.1.3.101 {
  SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
} {SEARCH t1 USING INDEX i1 (x>? AND x<?)}
set l 0
set u 1100
do_eqp_test analyze3-1.1.3.102 {
  SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {SCAN TABLE t1}
} {SCAN t1}
db cache flush
sqlite3_db_config db ENABLE_QPSG 1
do_eqp_test analyze3-1.1.3.103 {
  SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
} {SEARCH t1 USING INDEX i1 (x>? AND x<?)}
db cache flush
sqlite3_db_config db ENABLE_QPSG 0
do_eqp_test analyze3-1.1.3.104 {
  SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
} {SCAN TABLE t1}
} {SCAN t1}

do_test analyze3-1.1.4 {
  sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
} {199 0 14850}
do_test analyze3-1.1.5 {
  set l [string range "200" 0 end]
  set u [string range "300" 0 end]
203
204
205
206
207
208
209
210

211
212
213

214
215
216
217
218
219
220
203
204
205
206
207
208
209

210
211
212

213
214
215
216
217
218
219
220







-
+


-
+







} {}
do_execsql_test analyze3-2.1.x {
  SELECT count(*) FROM t2 WHERE x>1 AND x<2;
  SELECT count(*) FROM t2 WHERE x>0 AND x<99;
} {200 990}
do_eqp_test analyze3-1.2.2 {
  SELECT sum(y) FROM t2 WHERE x>1 AND x<2
} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}
} {SEARCH t2 USING INDEX i2 (x>? AND x<?)}
do_eqp_test analyze3-1.2.3 {
  SELECT sum(y) FROM t2 WHERE x>0 AND x<99
} {SCAN TABLE t2}
} {SCAN t2}

do_test analyze3-1.2.4 {
  sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
} {161 0 4760}
do_test analyze3-1.2.5 {
  set l [string range "12" 0 end]
  set u [string range "20" 0 end]
255
256
257
258
259
260
261
262

263
264
265

266
267
268
269
270
271
272
255
256
257
258
259
260
261

262
263
264

265
266
267
268
269
270
271
272







-
+


-
+







} {}
do_execsql_test analyze3-1.3.x {
  SELECT count(*) FROM t3 WHERE x>200 AND x<300;
  SELECT count(*) FROM t3 WHERE x>0 AND x<1100
} {99 1000}
do_eqp_test analyze3-1.3.2 {
  SELECT sum(y) FROM t3 WHERE x>200 AND x<300
} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}
} {SEARCH t3 USING INDEX i3 (x>? AND x<?)}
do_eqp_test analyze3-1.3.3 {
  SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
} {SCAN TABLE t3}
} {SCAN t3}

do_test analyze3-1.3.4 {
  sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
} {199 0 14850}
do_test analyze3-1.3.5 {
  set l [string range "200" 0 end]
  set u [string range "300" 0 end]
310
311
312
313
314
315
316
317

318
319
320

321
322
323
324
325
326
327
310
311
312
313
314
315
316

317
318
319

320
321
322
323
324
325
326
327







-
+


-
+







    append t [lindex {a b c d e f g h i j} [expr ($i%10)]]
    execsql { INSERT INTO t1 VALUES($i, $t) }
  }
  execsql COMMIT
} {}
do_eqp_test analyze3-2.2 {
  SELECT count(a) FROM t1 WHERE b LIKE 'a%'
} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}
} {SEARCH t1 USING INDEX i1 (b>? AND b<?)}
do_eqp_test analyze3-2.3 {
  SELECT count(a) FROM t1 WHERE b LIKE '%a'
} {SCAN TABLE t1}
} {SCAN t1}

# Return the first argument if like_match_blobs is true (the default)
# or the second argument if not
#
proc ilmb {a b} {
  ifcapable like_match_blobs {return $a}
  return $b
700
701
702
703
704
705
706
707

708
709
710
711

712
713
714
715
716
717
718
700
701
702
703
704
705
706

707
708
709
710

711
712
713
714
715
716
717
718







-
+



-
+







  }
  execsql COMMIT
  execsql ANALYZE
} {}

do_eqp_test analyze3-6-3 {
  SELECT * FROM t1 WHERE a = 5 AND c = 13;
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
} {SEARCH t1 USING INDEX i2 (c=?)}

do_eqp_test analyze3-6-2 {
  SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
} {SEARCH t1 USING INDEX i2 (c=?)}

#-----------------------------------------------------------------------------
# 2015-04-20.
# Memory leak in sqlite3Stat4ProbeFree().  (Discovered while fuzzing.)
#
do_execsql_test analyze-7.1 {
  DROP TABLE IF EXISTS t1;
Changes to test/analyze4.test.
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48







-
+







    INSERT INTO t1 SELECT a+32, b FROM t1;
    INSERT INTO t1 SELECT a+64, b FROM t1;
    ANALYZE;
  }

  # Should choose the t1a index since it is more specific than t1b.
  db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}

# Verify that the t1b index shows that it does not narrow down the
# search any at all.
#
do_test analyze4-1.1 {
  db eval {
    SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
Changes to test/analyze6.test.
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
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







-
+








-
-
+
+














-
+


-
+


-
+






-
+


-
+


-
+









-
+


-
+


-
+


# The lowest cost plan is to scan CAT and for each integer there, do a single
# lookup of the first corresponding entry in EV then read off the equal values
# in EV.  (Prior to the 2011-03-04 enhancement to where.c, this query would
# have used EV for the outer loop instead of CAT - which was about 3x slower.)
#
do_test analyze6-1.1 {
  eqp {SELECT count(*) FROM ev, cat WHERE x=y}
} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
} {/*SCAN cat USING COVERING INDEX catx*SEARCH ev USING COVERING INDEX evy (y=?)*/}

# The same plan is chosen regardless of the order of the tables in the
# FROM clause.
#
do_eqp_test analyze6-1.2 {
  SELECT count(*) FROM cat, ev WHERE x=y
} {
  QUERY PLAN
  |--SCAN TABLE cat USING COVERING INDEX catx
  `--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
  |--SCAN cat USING COVERING INDEX catx
  `--SEARCH ev USING COVERING INDEX evy (y=?)
}


# Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30
# If ANALYZE is run on an empty table, make sure indices are used
# on the table.
#
do_test analyze6-2.1 {
  execsql {
    CREATE TABLE t201(x INTEGER PRIMARY KEY, y UNIQUE, z);
    CREATE INDEX t201z ON t201(z);
    ANALYZE;
  }
  eqp {SELECT * FROM t201 WHERE z=5}
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.2 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.3 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.4 {
  execsql {
    INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
    ANALYZE t201;
  }
  eqp {SELECT * FROM t201 WHERE z=5}
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.5 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.6 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
do_test analyze6-2.7 {
  execsql {
    INSERT INTO t201 VALUES(4,5,7);
    INSERT INTO t201 SELECT x+100, y+100, z+100 FROM t201;
    INSERT INTO t201 SELECT x+200, y+200, z+200 FROM t201;
    INSERT INTO t201 SELECT x+400, y+400, z+400 FROM t201;
    ANALYZE t201;
  }
  eqp {SELECT * FROM t201 WHERE z=5}
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
} {/*SEARCH t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.8 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.9 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
} {/*SEARCH t201 USING INTEGER PRIMARY KEY (rowid=?)*/}

finish_test
Changes to test/analyze7.test.
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
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







-
+


-
+


-
+









-
+


-
+


-
+






-
+








-
+


-
+


-
+





-
+





-
+



-
+




-
+


-
+



-
+


    CREATE INDEX t1b ON t1(b);
    CREATE INDEX t1cd ON t1(c,d);
    CREATE VIRTUAL TABLE nums USING wholenumber;
    INSERT INTO t1 SELECT value, value, value/100, value FROM nums
                    WHERE value BETWEEN 1 AND 256;
    EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
  }
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-1.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-1.2 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}

# Run an analyze on one of the three indices.  Verify that this
# effects the row-count estimate on the one query that uses that
# one index.
#
do_test analyze7-2.0 {
  execsql {ANALYZE t1a;}
  db cache flush
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-2.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-2.2 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}

# Verify that since the query planner now things that t1a is more
# selective than t1b, it prefers to use t1a.
#
do_test analyze7-2.3 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}

# Run an analysis on another of the three indices.  Verify  that this
# new analysis works and does not disrupt the previous analysis.
#
do_test analyze7-3.0 {
  execsql {ANALYZE t1cd;}
  db cache flush;
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test analyze7-3.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.2.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
ifcapable stat4 {
  # If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
  # row count for (c=2) than it does for (c=?).
  do_test analyze7-3.2.2 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
  } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
  } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
} else {
  # If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
  # same as that for (c=?).
  do_test analyze7-3.2.3 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
  } {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
  } {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
}
do_test analyze7-3.3 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}

ifcapable {!stat4} {
  do_test analyze7-3.4 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
  } {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
  } {/*SEARCH t1 USING INDEX t1b (b=?)*/}
  do_test analyze7-3.5 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
  } {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
  } {/*SEARCH t1 USING INDEX t1a (a=?)*/}
}
do_test analyze7-3.6 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
} {/*SEARCH t1 USING INDEX t1cd (c=? AND d=?)*/}

finish_test
Changes to test/analyze8.test.
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
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+



















-
+



-
+


-
+



-
+


# with a==100.  And so for those cases, choose the t1b index.
#
# Buf ro a==99 and a==101, there are far fewer rows so choose
# the t1a index.
#
do_test 1.1 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.2 {
  eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.3 {
  eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.4 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.5 {
  eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.6 {
  eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 2.1 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
} {/*SEARCH t1 USING INDEX t1b (b>? AND b<?)*/}

# There are many more values of c between 0 and 100000 than there are
# between 800000 and 900000.  So t1c is more selective for the latter
# range.
# 
# Test 3.2 is a little unstable. It depends on the planner estimating
# that (b BETWEEN 30 AND 34) will match more rows than (c BETWEEN
# 800000 AND 900000). Which is a pretty close call (50 vs. 32), so
# the planner could get it wrong with an unlucky set of samples. This
# case happens to work, but others ("b BETWEEN 40 AND 44" for example) 
# will fail.
#
do_execsql_test 3.0 {
  SELECT count(*) FROM t1 WHERE b BETWEEN 30 AND 34;
  SELECT count(*) FROM t1 WHERE c BETWEEN 0 AND 100000;
  SELECT count(*) FROM t1 WHERE c BETWEEN 800000 AND 900000;
} {50 376 32}
do_test 3.1 {
  eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
} {/*SEARCH t1 USING INDEX t1b (b>? AND b<?)*/}
do_test 3.2 {
  eqp {SELECT * FROM t1
       WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
} {/*SEARCH t1 USING INDEX t1c (c>? AND c<?)*/}
do_test 3.3 {
  eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 3.4 {
  eqp {SELECT * FROM t1
       WHERE a=100 AND c BETWEEN 800000 AND 900000}
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
} {/*SEARCH t1 USING INDEX t1c (c>? AND c<?)*/}

finish_test
Changes to test/analyze9.test.
574
575
576
577
578
579
580
581

582
583
584

585
586
587

588
589
590

591
592
593
594
595
596
597
574
575
576
577
578
579
580

581
582
583

584
585
586

587
588
589

590
591
592
593
594
595
596
597







-
+


-
+


-
+


-
+







    if {$i %2} {set a abc} else {set a def}
    execsql { INSERT INTO t1(rowid, a, b, c) VALUES($i, $a, $i, $i) }
  }
  execsql ANALYZE
} {}
do_eqp_test 13.2.1 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<12
} {/SEARCH TABLE t1 USING INDEX i1/}
} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
} {/SEARCH TABLE t1 USING INDEX i1/}
} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
} {/SEARCH TABLE t1 USING INDEX i2/}
} {/SEARCH t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
} {/SEARCH TABLE t1 USING INDEX i2/}
} {/SEARCH t1 USING INDEX i2/}

#-------------------------------------------------------------------------
# Check also that affinities are taken into account when using stat4 data 
# to estimate the number of rows scanned by any other constraint on a 
# column other than the leftmost.
#
drop_all_tables
605
606
607
608
609
610
611
612

613
614
615

616
617
618
619
620
621
622
605
606
607
608
609
610
611

612
613
614

615
616
617
618
619
620
621
622







-
+


-
+







    CREATE INDEX i1 ON t1(a, b);
    CREATE INDEX i2 ON t1(c);
    ANALYZE;
  }
} {}
do_eqp_test 13.2.1 {
  SELECT * FROM t1 WHERE a='ott' AND b<10 AND c=1
} {/SEARCH TABLE t1 USING INDEX i1/}
} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
} {/SEARCH TABLE t1 USING INDEX i1/}
} {/SEARCH t1 USING INDEX i1/}

#-------------------------------------------------------------------------
# By default, 16 non-periodic samples are collected for the stat4 table.
# The following tests attempt to verify that the most common keys are
# being collected.
#
proc check_stat4 {tn} {
1052
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070







-
+



-
+








do_eqp_test 23.1 {
  SELECT * FROM t4 WHERE 
    (e=1 AND b='xyz' AND c='zyx' AND a<'AEA') AND f<300
  -- Formerly used index i41.  But i41 is not a covering index whereas
  -- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
  -- PRIMARY KEY is preferred.
} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
} {SEARCH t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
do_eqp_test 23.2 {
  SELECT * FROM t4 WHERE 
    (e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
} {SEARCH TABLE t4 USING INDEX i42 (f<?)}
} {SEARCH t4 USING INDEX i42 (f<?)}

do_execsql_test 24.0 {
  CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
  WITH data(a, b, c, d, e) AS (
    SELECT 'z', 'y', 0, 0, 0
    UNION ALL
    SELECT 
1102
1103
1104
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
1130
1131
1132
1133
1134
1102
1103
1104
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
1130
1131
1132
1133
1134







-
+

-
+




-
+






-
+



-
+







    CREATE INDEX bb ON t6(b);
    ANALYZE;
  }

  # Term (b<?) is estimated at 25%. Better than (a<30) but not as
  # good as (a<20).
  do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } \
    {SEARCH TABLE t6 USING INDEX bb (b<?)}
    {SEARCH t6 USING INDEX bb (b<?)}
  do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
    {SEARCH TABLE t6 USING INDEX aa (a<?)}
    {SEARCH t6 USING INDEX aa (a<?)}

  # Term (b BETWEEN ? AND ?) is estimated at 1/64.
  do_eqp_test 25.3.1 { 
    SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ? 
  } {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  } {SEARCH t6 USING INDEX bb (b>? AND b<?)}
  
  # Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
  # 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
  # (a<20) but not as good as (a<10).
  do_eqp_test 25.4.1 { 
    SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
  } {SEARCH TABLE t6 USING INDEX aa (a<?)}
  } {SEARCH t6 USING INDEX aa (a<?)}

  do_eqp_test 25.4.2 { 
    SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
  } {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
  } {SEARCH t6 USING INDEX bb (b>? AND b<?)}
}

#-------------------------------------------------------------------------
# Check that a problem in they way stat4 data is used has been 
# resolved (see below).
#
reset_db
1176
1177
1178
1179
1180
1181
1182
1183

1184
1185
1186
1187
1188
1189
1190
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
1190







-
+







# no more than that. Guessing less than 20 is therefore unreasonable.
#
# At one point though, due to a problem in whereKeyStats(), the planner was
# estimating that (x=10000 AND y<50) would match only 2 rows.
#
do_eqp_test 26.1.4 {
  SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
} {SEARCH t1 USING INDEX t1z (z=?)}


# This test - 26.2.* - tests that another manifestation of the same problem
# is no longer present in the library. Assuming:
# 
#   CREATE INDEX t1xy ON t1(x, y)
#
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1225
1226
1227
1228
1229
1230
1231

1232
1233
1234
1235







-
+



    UPDATE t1 SET z = (rowid / 95);
    ANALYZE;
  COMMIT;
}

do_eqp_test 26.2.2 {
  SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
} {SEARCH t1 USING INDEX i1 (x=? AND y>?)}


finish_test
Changes to test/analyzeC.test.
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
46
47
48
49
50
51
52

53
54
55
56
57
58
59
60







-
+







} {/.* USING INDEX t1a .a>. AND a<...*/}
do_execsql_test 1.2 {
  SELECT c FROM t1 ORDER BY a;
} {3 111 6 12 9 12}
do_execsql_test 1.3 {
  EXPLAIN QUERY PLAN
  SELECT c FROM t1 ORDER BY a;
} {/.*SCAN TABLE t1 USING INDEX t1a.*/}
} {/.*SCAN t1 USING INDEX t1a.*/}
do_execsql_test 1.3x {
  EXPLAIN QUERY PLAN
  SELECT c FROM t1 ORDER BY a;
} {~/.*B-TREE FOR ORDER BY.*/}

# Now mark the t1a index as "unordered".  Range queries and ORDER BY no
# longer use the index, but equality queries do.
Changes to test/analyzeD.test.
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
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







-
+














-
+










-
+












-
+


} {}

# With full ANALYZE data, SQLite sees that c=150 (5 rows) is better than
# a=3001 (7 rows).
#
do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a=3001 AND c=150;
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
} {SEARCH t1 USING INDEX t1_c (c=?)}

do_test 1.3 {
  execsql { DELETE FROM sqlite_stat1 }
  db close
  sqlite3 db test.db
} {}

# Without stat1, because 3001 is larger than all samples in the stat4
# table, SQLite thinks that a=3001 matches just 1 row. So it (incorrectly)
# chooses it over the c=150 index (5 rows). Even with stat1 data, things
# worked this way before commit [e6f7f97dbc].
#
do_eqp_test 1.4 {
  SELECT * FROM t1 WHERE a=3001 AND c=150;
} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
} {SEARCH t1 USING INDEX t1_ab (a=?)}

do_test 1.5 {
  execsql { 
    UPDATE t1 SET a=13 WHERE a = 3001;
    ANALYZE;
  }
} {}

do_eqp_test 1.6 {
  SELECT * FROM t1 WHERE a=13 AND c=150;
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
} {SEARCH t1 USING INDEX t1_c (c=?)}

do_test 1.7 {
  execsql { DELETE FROM sqlite_stat1 }
  db close
  sqlite3 db test.db
} {}

# Same test as 1.4, except this time the 7 rows that match the a=? condition 
# do not feature larger values than all rows in the stat4 table. So SQLite
# gets this right, even without stat1 data.
do_eqp_test 1.8 {
  SELECT * FROM t1 WHERE a=13 AND c=150;
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
} {SEARCH t1 USING INDEX t1_c (c=?)}

finish_test
Changes to test/analyzeE.test.
32
33
34
35
36
37
38
39

40
41
42
43

44
45
46
47

48
49
50
51

52
53
54
55

56
57
58
59

60
61
62
63

64
65
66
67

68
69
70
71

72
73
74
75

76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95

96
97
98
99

100
101
102
103

104
105
106
107

108
109
110
111

112
113
114
115

116
117
118
119

120
121
122
123

124
125
126
127

128
129
130
131

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152

153
154
155
156

157
158
159
160

161
162
163
164

165
166
167
168

169
170
171
172

173
174
175
176

177
178
179
180

181
182
183
184

185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204

205
206
207
208

209
210
211
212

213
214
215
216

217
218
219
220

221
222
223
224

225
226
227
228

229
230
231
232

233
234
235
236

237
238
239
240

241
242
32
33
34
35
36
37
38

39
40
41
42

43
44
45
46

47
48
49
50

51
52
53
54

55
56
57
58

59
60
61
62

63
64
65
66

67
68
69
70

71
72
73
74

75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90

91
92
93
94

95
96
97
98

99
100
101
102

103
104
105
106

107
108
109
110

111
112
113
114

115
116
117
118

119
120
121
122

123
124
125
126

127
128
129
130

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

148
149
150
151

152
153
154
155

156
157
158
159

160
161
162
163

164
165
166
167

168
169
170
171

172
173
174
175

176
177
178
179

180
181
182
183

184
185
186
187

188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203

204
205
206
207

208
209
210
211

212
213
214
215

216
217
218
219

220
221
222
223

224
225
226
227

228
229
230
231

232
233
234
235

236
237
238
239

240
241
242







-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+











-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+
















-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+











-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+



-
+


  INSERT INTO t1(a,b) SELECT x, x FROM cnt;
  CREATE INDEX t1a ON t1(a);
  ANALYZE;
} {}
do_execsql_test analyzeE-1.1 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-1.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-1.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE t1/}
} {/SCAN t1/}

# Verify that everything works the same on a DESCENDING index.
#
do_execsql_test analyzeE-2.0 {
  DROP INDEX t1a;
  CREATE INDEX t1a ON t1(a DESC);
  ANALYZE;
} {}
do_execsql_test analyzeE-2.1 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500;
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-2.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-2.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE t1/}
} {/SCAN t1/}

# Now do a range query on the second term of an ASCENDING index
# where the first term is constrained by equality.
#
do_execsql_test analyzeE-3.0 {
  DROP TABLE t1;
  CREATE TABLE t1(a,b,c);
  WITH RECURSIVE
    cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000)
  INSERT INTO t1(a,b,c) SELECT x, x, 123 FROM cnt;
  CREATE INDEX t1ca ON t1(c,a);
  ANALYZE;
} {}
do_execsql_test analyzeE-3.1 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-3.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-3.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900 AND c=123
} {/SCAN TABLE t1/}
} {/SCAN t1/}

# Repeat the 3.x tests using a DESCENDING index
#
do_execsql_test analyzeE-4.0 {
  DROP INDEX t1ca;
  CREATE INDEX t1ca ON t1(c ASC,a DESC);
  ANALYZE;
} {}
do_execsql_test analyzeE-4.1 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500 AND c=123;
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-4.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750 AND c=123;
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN TABLE t1/}
} {/SCAN t1/}
do_execsql_test analyzeE-4.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE t1 USING INDEX t1ca/}
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900 AND c=123
} {/SCAN TABLE t1/}
} {/SCAN t1/}

finish_test
Changes to test/analyzeF.test.
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72







-
+








  9  "x = str('19') AND y = str('4')" {t1y (y=?)}
  10 "x = str('4') AND y = str('19')" {t1y (y=?)}

  11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
  12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
} {
  set res "SEARCH TABLE t1 USING INDEX $idx"
  set res "SEARCH t1 USING INDEX $idx"
  do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
}

# Test that functions that do not exist - "func()" - do not cause an error.
#
do_catchsql_test 2.1 {
  SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
88
89
90
91
92
93
94
95

96
97
98
99
100
101
102
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102







-
+







foreach {tn where idx} {
  1 "x = det4() AND y = det19()"     {t1x (x=?)}
  2 "x = det19() AND y = det4()"     {t1y (y=?)}

  3 "x = nondet4() AND y = nondet19()"     {t1y (y=?)}
  4 "x = nondet19() AND y = nondet4()"     {t1y (y=?)}
} {
  set res "SEARCH TABLE t1 USING INDEX $idx"
  set res "SEARCH t1 USING INDEX $idx"
  do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
}


execsql { DELETE FROM t1 }

proc throw_error {err} { error $err }
Changes to test/analyzeG.test.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
16
17
18
19
20
21
22










23
24
25
26
27
28
29







-
-
-
-
-
-
-
-
-
-








ifcapable !stat4 {
  finish_test
  return
}
set testprefix analyzeG

proc do_scan_order_test {tn sql expect} {
  uplevel [list do_test $tn [subst -nocommands {
    set res ""
    db eval "explain query plan $sql" {
      lappend res [set detail]
    }
    set res
  }] [list {*}$expect]]
}

#-------------------------------------------------------------------------
# Test cases 1.* seek to verify that even if an index is not used, its
# stat4 data may be used by the planner to estimate the number of
# rows that match an unindexed constraint on the same column.
#
do_execsql_test 1.0 {
  PRAGMA automatic_index = 0;
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
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







-
+


-
+

-
+


+
-
+
+










-
+


+
-
+
+

-
+


+
-
+
+




}

# Join tables t1 and t2. Both contain 100 rows. (a=44) matches 2 rows
# in "t1", (b=44) matches 95 rows in table "t2". But the planner doesn't
# know this, so it has no preference as to which order the tables are
# scanned in. In practice this means that tables are scanned in the order
# they are specified in in the FROM clause.
do_scan_order_test 1.1.1 {
do_eqp_test 1.1.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
  {SCAN TABLE t1} {SCAN TABLE t2}

}
do_scan_order_test 1.1.2 {
do_eqp_test 1.1.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {
  QUERY PLAN
  {SCAN TABLE t2} {SCAN TABLE t1} 
  |--SCAN t2
  `--SCAN t1
}

do_execsql_test 1.2 {
  CREATE INDEX t2b ON t2(b);
  ANALYZE;
}

# Now, with the ANALYZE data, the planner knows that (b=44) matches a 
# large number of rows. So it elects to scan table "t1" first, regardless
# of the order in which the tables are specified in the FROM clause.
do_scan_order_test 1.3.1 {
do_eqp_test 1.3.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
  QUERY PLAN
  {SCAN TABLE t1} {SCAN TABLE t2}
  |--SCAN t1
  `--SCAN t2
}
do_scan_order_test 1.3.2 {
do_eqp_test 1.3.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {
  QUERY PLAN
  {SCAN TABLE t1} {SCAN TABLE t2} 
  |--SCAN t1
  `--SCAN t2
}


finish_test
Changes to test/attach4.test.
131
132
133
134
135
136
137
138
131
132
133
134
135
136
137








-
}

do_execsql_test 2.2 {
  DROP TRIGGER tr1;
}

finish_test

Changes to test/autoindex1.test.
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
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







-
+

-
+






-
+

-
+







-
+

-
+







  ANALYZE sqlite_master;
}
do_eqp_test autoindex1-500.1 {
  SELECT b FROM t501
   WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
} {
  QUERY PLAN
  |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
  `--LIST SUBQUERY xxxxxx
     `--SCAN TABLE t502
     `--SCAN t502
}
do_eqp_test autoindex1-501 {
  SELECT b FROM t501
   WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
  QUERY PLAN
  |--SCAN TABLE t501
  |--SCAN t501
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
     `--SEARCH t502 USING AUTOMATIC COVERING INDEX (y=?)
}
do_eqp_test autoindex1-502 {
  SELECT b FROM t501
   WHERE t501.a=123
     AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
} {
  QUERY PLAN
  |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH t501 USING INTEGER PRIMARY KEY (rowid=?)
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--SCAN TABLE t502
     `--SCAN t502
}

# The following code checks a performance regression reported on the
# mailing list on 2010-10-19.  The problem is that the nRowEst field
# of ephermeral tables was not being initialized correctly and so no
# automatic index was being created for the emphemeral table when it was
# used as part of a join.
273
274
275
276
277
278
279
280
281
282



283
284
285
286



287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
273
274
275
276
277
278
279



280
281
282
283



284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304







-
-
-
+
+
+

-
-
-
+
+
+










-
+







           AND later.owner_change_date > prev.owner_change_date
           AND later.owner_change_date <= s.date_of_registration||' 00:00:00')
       ) y ON x.sheep_no = y.sheep_no
   WHERE y.sheep_no IS NULL
   ORDER BY x.registering_flock;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--SCAN TABLE sheep AS s
  |  |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
  |--MATERIALIZE y
  |  |--SCAN s
  |  |--SEARCH prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
  |  `--CORRELATED SCALAR SUBQUERY xxxxxx
  |     `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
  |--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
  `--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
  |     `--SEARCH later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
  |--SCAN x USING INDEX sheep_reg_flock_index
  `--SEARCH y USING AUTOMATIC COVERING INDEX (sheep_no=?)
}


do_execsql_test autoindex1-700 {
  CREATE TABLE t5(a, b, c);
}
do_eqp_test autoindex1-700a {
  SELECT a FROM t5 WHERE b=10 ORDER BY c;
} {
  QUERY PLAN
  |--SCAN TABLE t5
  |--SCAN t5
  `--USE TEMP B-TREE FOR ORDER BY
}

# The following checks a performance issue reported on the sqlite-dev
# mailing list on 2013-01-10
#
do_execsql_test autoindex1-800 {
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424

425
426
427
428
429
430
431
409
410
411
412
413
414
415

416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431







-
+







-
+







  
  EXPLAIN QUERY PLAN
  SELECT * FROM 
        data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
             JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
             JOIN accounts ON (raw_contacts.account_id=accounts._id)
   WHERE mimetype_id=10 AND data14 IS NOT NULL;
} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
} {/SEARCH data .*SEARCH raw_contacts/}
do_execsql_test autoindex1-801 {
  EXPLAIN QUERY PLAN
  SELECT * FROM 
        data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
             JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
             JOIN accounts ON (raw_contacts.account_id=accounts._id)
   WHERE mimetypes._id=10 AND data14 IS NOT NULL;
} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
} {/SEARCH data .*SEARCH raw_contacts/}

# Another test case from an important user of SQLite.  The key feature of
# this test is that the "aggindex" subquery should make use of an
# automatic index.  If it does, the query is fast.  If it does not, the
# query is deathly slow.  It worked OK in 3.7.17 but started going slow
# with version 3.8.0.  The problem was fixed for 3.8.7 by reducing the
# cost estimate for automatic indexes on views and subqueries.
Changes to test/autoindex3.test.
70
71
72
73
74
75
76
77
78


79
80
81
82
83
84
85
86
87
88
89


90
91
92
93
70
71
72
73
74
75
76


77
78
79
80
81
82
83
84
85
86
87


88
89
90
91
92
93







-
-
+
+









-
-
+
+





  DROP TABLE IF EXISTS sqlite_stat4;
  ANALYZE sqlite_master;
}

# At one point, SQLite was using the inferior plan:
#
#   0|0|1|SEARCH TABLE v USING INDEX ve (e>?)
#   0|1|0|SEARCH TABLE u USING COVERING INDEX uab (ANY(a) AND b=?)
#   0|0|1|SEARCH v USING INDEX ve (e>?)
#   0|1|0|SEARCH u USING COVERING INDEX uab (ANY(a) AND b=?)
#
# on the basis that the real index "uab" must be better than the automatic
# index. This is not right - a skip-scan is not necessarily better than an
# automatic index scan.
#
do_eqp_test 220 {
  select count(*) from u, v where u.b = v.b and v.e > 34;
} {
  QUERY PLAN
  |--SEARCH TABLE v USING INDEX ve (e>?)
  `--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
  |--SEARCH v USING INDEX ve (e>?)
  `--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
}


finish_test
Changes to test/autoindex5.test.
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
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







-
+




















-
+












-
+







  WHERE
     sp.rowid = st.package
     AND st.bug_name = bugs.name
     AND ( st.bug_name LIKE 'CVE-%' OR st.bug_name LIKE 'TEMP-%' )
     AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
            OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
  ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
} {SEARCH debian_cve USING AUTOMATIC COVERING INDEX (bug_name=?)}

#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
#
do_execsql_test 2.1 {
  CREATE TABLE one(o);
  INSERT INTO one DEFAULT VALUES;

  CREATE TABLE t1(x, z);
  INSERT INTO t1 VALUES('aaa', 4.0);
  INSERT INTO t1 VALUES('aaa', 4.0);
  CREATE VIEW vvv AS
    SELECT * FROM t1
    UNION ALL
    SELECT 0, 0 WHERE 0;

  SELECT (
      SELECT sum(z) FROM vvv WHERE x='aaa'
  ) FROM one;
} {8.0}
do_execsql_test 2.2 {
do_catchsql_test 2.2 {
  DROP TABLE t1;
  CREATE TABLE t1(aaa);
  INSERT INTO t1(aaa) VALUES(9);
  SELECT (
    SELECT aaa FROM t1 GROUP BY (
      SELECT bbb FROM (
        SELECT ccc AS bbb FROM (
           SELECT 1 ccc
        ) WHERE rowid IS NOT 1
      ) WHERE bbb = 1
    )
  );
} {9}
} {1 {no such column: rowid}}

# Ticket https://www.sqlite.org/src/info/787fa716be3a7f65
# Segfault due to multiple uses of the same subquery where the
# subquery is implemented via coroutine.
#
ifcapable windowfunc {
sqlite3 db :memory:
Changes to test/bestindex1.test.
47
48
49
50
51
52
53
54

55
56
57
58

59
60
61
62
63
64
65
47
48
49
50
51
52
53

54
55
56
57

58
59
60
61
62
63
64
65







-
+



-
+








do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
} {}

do_eqp_test 1.1 {
  SELECT * FROM x1 WHERE a = 'abc'
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}

do_eqp_test 1.2 {
  SELECT * FROM x1 WHERE a IN ('abc', 'def');
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}

#-------------------------------------------------------------------------
#
reset_db
register_tcl_module db

# Parameter $mode may be one of:
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
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







-
+




-
+




-
+








  do_execsql_test 2.2.$mode.5 {
    SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
  } {1 4} 

  set plan(use) {
    QUERY PLAN
    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
    |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
    `--USE TEMP B-TREE FOR ORDER BY
  }
  set plan(omit) {
    QUERY PLAN
    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
    |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
    `--USE TEMP B-TREE FOR ORDER BY
  }
  set plan(use2) {
    QUERY PLAN
    |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
    |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
    `--USE TEMP B-TREE FOR ORDER BY
  }

  do_eqp_test 2.2.$mode.6 { 
    SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
  } [string map {"\n  " "\n"} $plan($mode)]
}
Changes to test/bestindex2.test.
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
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







-
+



-
+



-
+





-
-
+
+






-
-
-
+
+
+






-
-
-
+
+
+










-
-
-
-
+
+
+
+



  CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd t1 {a b}");
  CREATE VIRTUAL TABLE t2 USING tcl("vtab_cmd t2 {c d}");
  CREATE VIRTUAL TABLE t3 USING tcl("vtab_cmd t3 {e f}");
}

do_eqp_test 1.1 {
  SELECT * FROM t1 WHERE a='abc'
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}

do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a='abc' AND b='def'
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}

do_eqp_test 1.3 {
  SELECT * FROM t1 WHERE a='abc' AND a='def'
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
} {SCAN t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}

do_eqp_test 1.4 {
  SELECT * FROM t1,t2 WHERE c=a
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
  `--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 0:
  `--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
}

do_eqp_test 1.5 {
  SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 0:
  |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}

do_eqp_test 1.6 {
  SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
} {
  QUERY PLAN
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
  |--SCAN t1 VIRTUAL TABLE INDEX 0:
  |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}

do_execsql_test 1.7.1 {
  CREATE TABLE x1(a, b);
}
do_eqp_test 1.7.2 {
  SELECT * FROM x1 CROSS JOIN t1, t2, t3 
    WHERE t1.a = t2.c AND t1.b = t3.e
} {
  QUERY PLAN
  |--SCAN TABLE x1
  |--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
  |--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
  |--SCAN x1
  |--SCAN t1 VIRTUAL TABLE INDEX 0:
  |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}

finish_test
Changes to test/bestindex3.test.
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
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







-
+



-
+







-
+

-
+








-
+

-
+








do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd 0");
}

do_eqp_test 1.1 {
  SELECT * FROM t1 WHERE a LIKE 'abc';
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
} {SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?}

do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a = 'abc';
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
} {SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?}

do_eqp_test 1.3 {
  SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
     |  `--SCAN t1 VIRTUAL TABLE INDEX 0:a EQ ?
     `--INDEX 2
        `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
        `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}

do_eqp_test 1.4 {
  SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def';
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
     |  `--SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?
     `--INDEX 2
        `--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
        `--SCAN t1 VIRTUAL TABLE INDEX 0:b EQ ?
}

do_execsql_test 1.5 {
  CREATE TABLE ttt(a, b, c);

  INSERT INTO ttt VALUES(1, 'two',   'three');
  INSERT INTO ttt VALUES(2, 'one',   'two');
151
152
153
154
155
156
157
158

159
160

161
162
163
164
165
166
167
151
152
153
154
155
156
157

158
159

160
161
162
163
164
165
166
167







-
+

-
+








  do_eqp_test 2.2 {
    SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
  } [string map {"\n  " \n} {
    QUERY PLAN
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)
       |  `--SEARCH t2 USING INDEX t2x (x>? AND x<?)
       `--INDEX 2
          `--SEARCH TABLE t2 USING INDEX t2y (y=?)
          `--SEARCH t2 USING INDEX t2y (y=?)
  }]
}

#-------------------------------------------------------------------------
# Test that any PRIMARY KEY within a sqlite3_decl_vtab() CREATE TABLE 
# statement is currently ignored.
#
Changes to test/bestindex4.test.
155
156
157
158
159
160
161
162
163


164
165
166
167
168
169
170
171


172
173
174
175
155
156
157
158
159
160
161


162
163
164
165
166
167
168
169


170
171
172
173
174
175







-
-
+
+






-
-
+
+




  CREATE TABLE t1 (x INT PRIMARY KEY);
} {}

do_eqp_test 2.1 {
  SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
  QUERY PLAN
  |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0:
  `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
  |--SCAN x1 VIRTUAL TABLE INDEX 0:
  `--SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
}

do_eqp_test 2.2 {
  SELECT * FROM t1, x1(t1.x)
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555:
  |--SCAN t1
  `--SCAN x1 VIRTUAL TABLE INDEX 555:
}


finish_test
Changes to test/bestindex7.test.
72
73
74
75
76
77
78
79
72
73
74
75
76
77
78








-
do_execsql_test 1.9 { select * from vt1 WHERE a=1 OR a=0} {0}
do_execsql_test 1.10 { select * from vt1 WHERE a IN (2) } {}
do_execsql_test 1.10 { select * from vt1 WHERE a IN (0,1,2,3) } {0}
do_execsql_test 1.11 { select * from vt1 WHERE a IN (0, NULL) } {0}
do_execsql_test 1.12 { select * from vt1 WHERE a IN (NULL) } {}

finish_test

Changes to test/between.test.
54
55
56
57
58
59
60
61
62


63
64

65
66
67
68
69
70
71
54
55
56
57
58
59
60


61
62
63

64
65
66
67
68
69
70
71







-
-
+
+

-
+







  set ::sqlite_sort_count 0
  set data [execsql $sql]
  if {$::sqlite_sort_count} {set x sort} {set x nosort}
  lappend data $x
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  # puts eqp=$eqp
  foreach {a b c x} $eqp {
    if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
    if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

do_test between-1.1.1 {
Changes to test/bigmmap.test.
90
91
92
93
94
95
96
97

98
99

100
101
102
103
104
90
91
92
93
94
95
96

97
98

99
100
101
102
103
104







-
+

-
+





    
    do_eqp_test 2.$i.$t.3 "
      SELECT * FROM t$t AS o WHERE 
        NOT EXISTS( SELECT * FROM t$t AS i WHERE a=o.a AND +b=o.b AND +c=o.c )
      ORDER BY b, c;
    " [string map {"\n    " "\n"} "
      QUERY PLAN
      |--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
      |--SCAN o USING COVERING INDEX sqlite_autoindex_t${t}_1
      `--CORRELATED SCALAR SUBQUERY xxxxxx
         `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
         `--SEARCH i USING INTEGER PRIMARY KEY (rowid=?)
    "]
  }
}

finish_test
Changes to test/busy2.test.
164
165
166
167
168
169
170
171
164
165
166
167
168
169
170








-
    set ::busy_called 0
    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
  } {1 1}

}

finish_test

Changes to test/columncount.test.
50
51
52
53
54
55
56
57
50
51
52
53
54
55
56








-
do_ccsql_test 1.5 { ALTER TABLE t3 ADD COLUMN d } {0}

do_ccsql_test 1.6 { DROP TABLE t3 } {0}



finish_test

Changes to test/corrupt4.test.
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26







-



+







#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests to make sure SQLite does not crash or
# segfault if it sees a corrupt database file.
#
# $Id: corrupt4.test,v 1.1 2007/09/07 14:32:07 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix corrupt4

# This module uses hard-coded offsets which do not work if the reserved_bytes
# value is nonzero.
if {[nonzero_reserved_bytes]} {finish_test; return;}

# These tests deal with corrupt database files
#
74
75
76
77
78
79
80
81

































































82
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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  hexio_write test.db [expr {$::baseaddr+4}] [hexio_render_int32 -100000000]
  db close
  sqlite3 db test.db
  catchsql {
    DROP TABLE t2
  }
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------

reset_db
do_execsql_test 2.0 {
  PRAGMA page_size = 512;
  CREATE TABLE t1(a, b, c);
}

# Create a database with a schema so large that the root of the 
# sqlite_schema table is the grandparent of its leaves.
#
set nView 1000
do_test 2.1 {
  execsql BEGIN
  for {set ii 0} {$ii<$nView} {incr ii} {
    execsql " CREATE VIEW v$ii AS SELECT a, b, c FROM t1 "
  }
  execsql COMMIT
} {}
db close

proc get2byte {fd offset} {
  seek $fd $offset
  set bin [read $fd 2]
  binary scan $bin S val
  set val
}
proc get4byte {fd offset} {
  seek $fd $offset
  set bin [read $fd 4]
  binary scan $bin I val
  set val
}
proc put4byte {fd offset val} {
  seek $fd $offset
  set bin [binary format I $val]
  puts -nonewline $fd $bin
}

# Page 1 is now the grandparent of its leaves. Corrupt the database by setting 
# the second rightmost child page number of page 1 to 1.
#
set fd [open test.db r+]
fconfigure $fd -encoding binary -translation binary
set nChild [get2byte $fd 103]
set offChild [get2byte $fd [expr 100+12+($nChild-2)*2]]
set pgnoChild [get4byte $fd $offChild]
put4byte $fd $offChild 1
close $fd

sqlite3 db test.db
do_catchsql_test 2.2 {
  PRAGMA writable_schema = 1;
  SELECT * FROM sqlite_schema;
} {1 {database disk image is malformed}}

do_test 2.3 {
  list [catch {
    for {set ii $nView} {$ii<$nView*2} {incr ii} {
      execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
    }
  } msg] $msg
} {1 {database disk image is malformed}}


finish_test
Changes to test/corruptL.test.
1333
1334
1335
1336
1337
1338
1339
























































































1340
1341
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
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
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


  } {1 {database disk image is malformed}}
  
  do_test 17.3 {
    close $fd
  } {}
}

#-------------------------------------------------------------------------
reset_db
do_test 18.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 12288 pagesize 4096 filename crash-40d5739835cbdb.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00   .....@  ........
|     96: 00 00 00 00 0d 00 00 00 02 0f 4e 00 0f a2 0f 4e   ..........N....N
|   3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 52 02   ..............R.
|   3920: 07 17 11 11 01 81 0f 74 61 62 6c 65 74 32 74 32   .......tablet2t2
|   3936: 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32   .CREATE TABLE t2
|   3952: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 45 47 45   (a INT, b INTEGE
|   3968: 52 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 61   R, PRIMARY KEY(a
|   3984: 2c 62 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57   ,b)) WITHOUT ROW
|   4000: 49 44 5c 01 07 16 11 11 01 81 23 74 61 62 6c 65   ID........#table
|   4016: 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c   t1t1.CREATE TABL
|   4032: 45 20 74 31 28 61 20 49 4e 54 20 50 52 49 4d 41   E t1(a INT PRIMA
|   4048: 52 59 20 4b 45 59 2c 20 62 20 54 45 58 54 2c 20   RY KEY, b TEXT, 
|   4064: 63 20 54 45 58 54 2c 20 64 20 49 4e 54 45 47 45   c TEXT, d INTEGE
|   4080: 52 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44   R) WITHOUT ROWID
| page 2 offset 4096
|      0: 0a 00 00 00 06 0f a7 00 0f f4 0f e5 0f d5 0f c5   ................
|     16: 0f b6 0f 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4000: 00 00 00 00 00 00 00 0f 05 01 15 13 01 06 65 7f   ..............e.
|   4016: 25 6e 73 69 78 06 0e 05 01 13 15 03 b5 6f 64 64   %nsix........odd
|   4032: 66 69 76 65 05 0f 05 01 15 15 01 04 65 76 65 61   five........evea
|   4048: e6 6f 75 82 04 0f 05 01 13 17 01 03 6f 64 64 74   .ou.........oddt
|   4064: 68 72 61 15 03 0e 05 01 15 12 01 02 64 76 64 6e   hra.........dvdn
|   4080: 74 77 6f 02 00 00 00 00 00 00 00 00 00 00 00 00   two.............
| page 3 offset 8192
|   2816: 00 00 00 00 00 00 00 00 00 00 00 06 03 02 01 00   ................
|   2832: c8 07 06 03 02 01 00 c7 11 06 03 02 01 02 a6 52   ...............R
|   2848: 06 d5 02 01 10 c5 1b 06 03 02 00 ef c4 53 06 03   .............S..
|   2864: 02 01 00 c3 22 06 04 02 01 00 c2 26 06 03 02 01   ...........&....
|   2880: 00 c2 1e 02 b3 02 01 00 c0 3a 06 03 3c 01 00 bf   .........:..<...
|   2896: 2c 06 03 02 01 00 be 27 00 83 02 01 01 bd 15 06   ,......'........
|   2912: 03 02 01 00 bc 21 06 03 02 01 00 bb 54 16 13 02   .....!......T...
|   2928: 01 09 9a 0a 06 03 02 01 00 b9 53 06 03 02 01 00   ..........S.....
|   2944: b8 52 06 13 02 01 00 b7 1e 06 03 02 01 00 b6 34   .R.............4
|   2960: 06 13 02 01 00 b5 3a 05 f3 12 01 00 b4 45 05 03   ......:......E..
|   2976: 02 00 00 b4 6f 06 03 02 01 00 b2 03 06 03 02 01   ....o...........
|   2992: 00 b1 63 06 03 02 01 00 b0 24 06 03 02 01 00 9f   ..c......$......
|   3008: ac 06 03 02 01 00 a2 2f 07 03 02 01 01 ad 21 06   ......./......!.
|   3024: 03 02 01 fb cd 5b 06 c0 01 f1 00 ab 23 06 03 02   .....[......#...
|   3040: 01 00 aa 5b 06 03 02 01 00 a3 ce 06 02 03 01 00   ...[............
|   3056: a8 0e 06 03 02 01 00 a7 0c 06 02 f1 01 00 a6 0d   ................
|   3072: 06 03 02 01 00 95 25 06 03 02 01 00 a4 17 06 03   ......%.........
|   3088: 02 01 00 a3 09 06 03 02 01 00 a2 51 06 03 02 02   ...........Q....
|   3104: 00 a1 40 06 01 e2 00 00 a0 4b 06 13 02 00 00 9e   ..@......K......
|   3120: 5d 06 03 02 01 10 9e 81 06 03 02 01 00 9d 42 06   ].............B.
|   3136: 03 69 01 00 9c 48 06 03 02 01 00 9b 48 06 03 01   .i...H......H...
|   3152: 01 00 9a 09 06 03 02 01 00 99 2f 06 03 02 01 00   ........../.....
|   3168: 98 3a 06 03 02 01 00 97 24 06 03 02 01 00 96 4a   .:......$......J
|   3184: 06 03 02 11 00 f9 50 02 93 02 01 00 94 2f 06 03   ......P....../..
|   3200: 02 11 04 93 1a 06 03 01 04 e0 92 1a 06 03 02 01   ................
|   3216: 00 91 27 06 03 02 01 00 90 23 06 03 02 01 00 8f   ..'......#......
|   3232: 3b 06 03 02 01 00 8e 46 06 16 02 01 00 8d 1d 07   ;......F........
|   3248: 23 12 01 00 8c 5a 06 03 02 01 00 8a 39 06 03 02   #....Z......9...
|   3264: 00 ff 84 b5 06 03 02 01 00 89 07 06 03 02 11 00   ................
|   3280: 88 02 06 03 02 01 00 87 19 06 03 02 01 00 86 4d   ...............M
|   3296: 06 13 12 00 00 85 4b 06 03 02 01 00 84 37 06 13   ......K......7..
|   3312: 02 01 00 83 2c 06 03 02 01 00 81 60 06 13 02 11   ....,......`....
|   3328: 00 81 3b 06 03 02 01 0a b0 5a 06 03 01 01 7f 22   ..;......Z......
|   3344: 05 03 01 01 7e 21 05 03 01 01 7d 0b 15 03 01 02   ....~!..........
|   3360: 7b 08 05 03 06 91 7b 22 05 03 01 01 7a 58 05 03   ............zX..
|   3376: 01 01 7a 4f 05 03 01 01 78 49 05 03 01 01 77 16   ..zO....xI....w.
|   3392: 05 03 01 01 76 5f 05 03 01 01 75 0f 05 03 01 01   ....v_....u.....
|   3408: 74 2f 05 03 01 01 3f 1f 05 03 01 02 72 14 05 03   t/....?.....r...
|   3424: 00 f1 71 08 05 03 01 01 70 0c 05 03 01 47 7f 29   ..q.....p....G.)
|   3440: 05 03 01 01 6e 57 05 03 01 01 6d 33 05 13 00 f1   ....nW....m3....
|   3456: 6c 0b 05 03 01 01 6b 49 05 03 01 01 69 05 05 03   l.....kI....i...
|   3472: 01 02 ed 23 00 00 01 00 00 00 00 00 00 00 00 00   ...#............
| end crash-40d5739835cbdb.db
}]} {}

ifcapable json1 {
do_catchsql_test 18.1 {
  SELECT 
    json_group_array(c) OVER win4 
  FROM t1
    WINDOW win4 AS (
        ORDER BY a COLLATE nocase RANGE BETWEEN 1.0 PRECEDING AND CURRENT ROW
    )
} {1 {JSON cannot hold BLOB values}}
} ;# ifcapable json1

finish_test
Changes to test/corruptN.test.
97
98
99
100
101
102
103















































































































104
105
106
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



|    448: ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00   ................
| end sql024239.txt.db
}]} {}

do_catchsql_test 1.1 {
  VACUUM;
} {1 {database disk image is malformed}}

# 2021-04-05 dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c-b92b.txt.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     96: 00 00 00 00 0d 0f f8 00 04 0f 12 00 0f 91 0f d3   ................
|    112: 0f 67 0f 12 00 00 00 00 00 00 00 00 00 00 00 00   .g..............
|   3856: 00 00 53 04 07 1b 13 11 08 81 0d 74 72 69 67 67   ..S........trigg
|   3872: 65 72 74 72 30 74 31 43 52 45 41 54 45 20 54 52   ertr0t1CREATE TR
|   3888: 49 47 47 45 52 20 74 72 30 20 44 45 4c 45 54 45   IGGER tr0 DELETE
|   3904: 20 4f 4e 20 74 31 20 42 45 47 49 4e 0a 20 20 55    ON t1 BEGIN.  U
|   3920: 50 44 41 54 45 20 74 31 20 53 45 54 20 62 20 3d   PDATE t1 SET b =
|   3936: 20 61 3b 0a 45 4e 44 28 03 06 17 11 11 01 3d 69    a;.END(......=i
|   3952: 6e 64 65 78 69 30 74 31 04 43 52 45 41 54 45 20   ndexi0t1.CREATE 
|   3968: 49 4e 44 45 58 20 69 30 20 4f 4e 20 74 31 28 62   INDEX i0 ON t1(b
|   3984: 29 40 01 06 17 11 11 01 6d 74 61 62 6c 65 74 31   )@......mtablet1
|   4000: 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20   t1.CREATE TABLE 
|   4016: 74 31 28 61 20 55 4e 49 51 55 45 20 4f 4e 20 43   t1(a UNIQUE ON C
|   4032: 4f 4e 46 4c 49 43 54 20 52 45 50 4c 41 43 45 2c   ONFLICT REPLACE,
|   4048: 20 62 29 23 02 06 17 37 11 01 00 69 6e 64 65 78    b)#...7...index
|   4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78   sqlite_autoindex
|   4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00   _t1_1t1.........
| page 2 offset 4096
|      0: 0d 00 00 00 02 0f 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 05 02 03 01 01 09 0d 05 01 03 01 01 04 0c   ................
| page 3 offset 8192
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 03 01 01 09 02 04 03 01 09 04   ................
| page 4 offset 12288
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 03 01 01 0d 02 04 03 00 00 00   ................
| end c-b92b.txt.db
}]} {}

prng_seed 0 db
do_catchsql_test 2.1 {
SELECT count(*) FROM sqlite_schema;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
INSERT INTO t1(a) SELECT randomblob(null) FROM c;
} {1 {database disk image is malformed}}

reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY AUTOINCREMENT, y);
  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema 
    SET sql = 'CREATE TABLE sqlite_sequence(name-seq)' 
    WHERE name = 'sqlite_sequence';
}
db close
sqlite3 db test.db
do_catchsql_test 3.1 {
  PRAGMA writable_schema = 1;
  INSERT INTO t1(y) VALUES('abc');
} {1 {database disk image is malformed}}

reset_db
do_execsql_test 4.1 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b UNIQUE, c UNIQUE);
  INSERT INTO x1 VALUES(1, 1, 2);
  INSERT INTO x1 VALUES(2, 2, 3);
  INSERT INTO x1 VALUES(3, 3, 4);
  INSERT INTO x1 VALUES(4, 5, 6);
  PRAGMA writable_schema = 1;

  UPDATE sqlite_schema SET rootpage = (
    SELECT rootpage FROM sqlite_schema WHERE name = 'sqlite_autoindex_x1_2'
  ) WHERE name = 'sqlite_autoindex_x1_1';
}

db close
sqlite3 db test.db
breakpoint
do_catchsql_test 3.1 {
  PRAGMA writable_schema = 1;
  REPLACE INTO x1 VALUES(5, 2, 3);
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------

reset_db
db func strreplace strreplace
proc strreplace {orig a b} {
  string map [list $a $b] $orig
}

do_execsql_test 4.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);

  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema 
    SET sql = strreplace(sql, 't1', 'json_each') 
    WHERE type='index';
}

db close
sqlite3 db test.db

do_execsql_test 4.1 {
  PRAGMA writable_schema = 1;
  SELECT * FROM t1
}



finish_test
Changes to test/cost.test.
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
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







-
-
+
+












-
+



















-
+

-
+

-
+



















-
+



-
+














-
+







-
+

















-
+

-
+







  CREATE UNIQUE INDEX i3 ON t3(b);
  CREATE UNIQUE INDEX i4 ON t4(c, d);
}
do_eqp_test 1.2 {
  SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
} {
  QUERY PLAN
  |--SCAN TABLE t3 USING COVERING INDEX i3
  `--SEARCH TABLE t4 USING INDEX i4 (c=?)
  |--SCAN t3 USING COVERING INDEX i3
  `--SEARCH t4 USING INDEX i4 (c=?)
}


do_execsql_test 2.1 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a);
}

# It is better to use an index for ORDER BY than sort externally, even 
# if the index is a non-covering index.
do_eqp_test 2.2 {
  SELECT * FROM t1 ORDER BY a;
} {SCAN TABLE t1 USING INDEX i1}
} {SCAN t1 USING INDEX i1}

do_execsql_test 3.1 {
  CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
  CREATE INDEX t5b ON t5(b);
  CREATE INDEX t5c ON t5(c);
  CREATE INDEX t5d ON t5(d);
  CREATE INDEX t5e ON t5(e);
  CREATE INDEX t5f ON t5(f);
  CREATE INDEX t5g ON t5(g);
}

do_eqp_test 3.2 {
  SELECT a FROM t5 
  WHERE b IS NULL OR c IS NULL OR d IS NULL 
  ORDER BY a;
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t5 USING INDEX t5b (b=?)
  |  |  `--SEARCH t5 USING INDEX t5b (b=?)
  |  |--INDEX 2
  |  |  `--SEARCH TABLE t5 USING INDEX t5c (c=?)
  |  |  `--SEARCH t5 USING INDEX t5c (c=?)
  |  `--INDEX 3
  |     `--SEARCH TABLE t5 USING INDEX t5d (d=?)
  |     `--SEARCH t5 USING INDEX t5d (d=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

#-------------------------------------------------------------------------
# If there is no likelihood() or stat3 data, SQLite assumes that a closed
# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint)
# visits 1/64 of the rows in a table.
#
# Note: 1/63 =~ 0.016
# Note: 1/65 =~ 0.015
#
reset_db
do_execsql_test 4.1 {
  CREATE TABLE t1(a, b);
  CREATE INDEX i1 ON t1(a);
  CREATE INDEX i2 ON t1(b);
}
do_eqp_test 4.2 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}

do_eqp_test 4.3 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
} {SEARCH t1 USING INDEX i2 (b>? AND b<?)}


#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.1 {
  CREATE TABLE t2(x, y);
  CREATE INDEX t2i1 ON t2(x);
}

do_eqp_test 5.2 {
  SELECT * FROM t2 ORDER BY x, y;
} {
  QUERY PLAN
  |--SCAN TABLE t2 USING INDEX t2i1
  |--SCAN t2 USING INDEX t2i1
  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_eqp_test 5.3 {
  SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
} {
  QUERY PLAN
  |--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)
  |--SEARCH t2 USING INDEX t2i1 (x>? AND x<?)
  `--USE TEMP B-TREE FOR ORDER BY
}

# where7.test, where8.test:
#
do_execsql_test 6.1 {
  CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
  CREATE INDEX t3i1 ON t3(b);
  CREATE INDEX t3i2 ON t3(c);
}

do_eqp_test 6.2 {
  SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)
  |  |  `--SEARCH t3 USING INDEX t3i1 (b>? AND b<?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
  |     `--SEARCH t3 USING INDEX t3i2 (c=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.1 {
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
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







-
+

-
+








-
+



-
+







  SELECT a FROM t1
     WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
  ORDER BY a
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)
  |  |  `--SEARCH t1 USING INDEX t1b (b>? AND b<?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t1 USING INDEX t1b (b=?)
  |     `--SEARCH t1 USING INDEX t1b (b=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

do_eqp_test 7.3 {
  SELECT rowid FROM t1
  WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
        OR (b NOT NULL AND c IS NULL AND d NOT NULL)
        OR (b NOT NULL AND c NOT NULL AND d IS NULL)
} {SCAN TABLE t1}
} {SCAN t1}

do_eqp_test 7.4 {
  SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
} {SCAN TABLE t1}
} {SCAN t1}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
  CREATE TABLE composer(
    cid INTEGER PRIMARY KEY,
198
199
200
201
202
203
204
205
206
207



208
209
210
211
212
213
214
198
199
200
201
202
203
204



205
206
207
208
209
210
211
212
213
214







-
-
-
+
+
+







  SELECT DISTINCT aname
    FROM album, composer, track
   WHERE cname LIKE '%bach%'
     AND unlikely(composer.cid=track.cid)
     AND unlikely(album.aid=track.aid);
} {
  QUERY PLAN
  |--SCAN TABLE track
  |--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN track
  |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

#-------------------------------------------------------------------------
#
do_execsql_test 9.1 {
  CREATE TABLE t1(
267
268
269
270
271
272
273
274

275
276
277
278

279
280
281
282

283
284
285
286

287
288
289
267
268
269
270
271
272
273

274
275
276
277

278
279
280
281

282
283
284
285

286
287
288
289







-
+



-
+



-
+



-
+



      execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) }
    }
    execsql ANALYZE
  } {}

  do_eqp_test 10.3 {
    SELECT rowid FROM t6 WHERE a=0 AND c=0
  } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
  } {SEARCH t6 USING INDEX t6i2 (c=?)}

  do_eqp_test 10.4 {
    SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
  } {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
  } {SEARCH t6 USING INDEX t6i2 (c=?)}

  do_eqp_test 10.5 {
    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
  } {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
  } {SEARCH t6 USING INDEX t6i1 (a=?)}

  do_eqp_test 10.6 {
    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
  } {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
  } {SEARCH t6 USING INDEX t6i1 (a=? AND b=?)}
}

finish_test
Changes to test/count.test.
208
209
210
211
212
213
214
215

216
217
218
219
220
221

222
223
224
225
226
227

228
229
230
231
232
233

234
235
236
237
208
209
210
211
212
213
214

215
216
217
218
219
220

221
222
223
224
225
226

227
228
229
230
231
232

233
234
235
236
237







-
+





-
+





-
+





-
+




  UPDATE sqlite_stat1 SET stat='1000000 10' WHERE idx='t1b';
  ANALYZE sqlite_master;
}
do_eqp_test count-7.2 {
  SELECT count(1) FROM t1;
} {
  QUERY PLAN
  `--SCAN TABLE t1 USING COVERING INDEX t1b
  `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.3 {
  SELECT count(1) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}
do_eqp_test count-7.3 {
  SELECT count(*) FROM t1;
} {
  QUERY PLAN
  `--SCAN TABLE t1 USING COVERING INDEX t1b
  `--SCAN t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.4 {
  SELECT count(*) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}


finish_test
Changes to test/coveridxscan.test.
105
106
107
108
109
110
111
112

113
114
115
116

117
118
119
105
106
107
108
109
110
111

112
113
114
115

116
117
118
119







-
+



-
+




  CREATE TABLE t2(i INTEGER PRIMARY KEY, $cols);
  CREATE INDEX i2 ON t2($cols);
"

do_eqp_test 5.1.1 {
  SELECT * FROM t1 ORDER BY c1, c2;
} {SCAN TABLE t1 USING COVERING INDEX i1}
} {SCAN t1 USING COVERING INDEX i1}

do_eqp_test 5.1.2 {
  SELECT * FROM t2 ORDER BY c1, c2;
} {SCAN TABLE t2 USING COVERING INDEX i2}
} {SCAN t2 USING COVERING INDEX i2}


finish_test
Changes to test/distinct.test.
26
27
28
29
30
31
32
33

34
35
36

37
38
39
40
41
42
43
44
45
26
27
28
29
30
31
32

33
34
35

36
37

38
39
40
41
42
43
44







-
+


-
+

-







proc is_distinct_noop {sql} {
  set sql1 $sql
  set sql2 [string map {DISTINCT ""} $sql]

  set program1 [list]
  set program2 [list]
  db eval "EXPLAIN $sql1" {
    if {$opcode != "Noop"} { lappend program1 $opcode }
    if {$opcode != "Noop" && $opcode != "Explain"} { lappend program1 $opcode }
  }
  db eval "EXPLAIN $sql2" {
    if {$opcode != "Noop"} { lappend program2 $opcode }
    if {$opcode != "Noop" && $opcode != "Explain"} { lappend program2 $opcode }
  }

  return [expr {$program1==$program2}]
}

proc do_distinct_noop_test {tn sql} {
  uplevel [list do_test $tn [list is_distinct_noop $sql] 1]
}
proc do_distinct_not_noop_test {tn sql} {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
123
124
125
126
127
128
129

130
131
132
133
134
135
136







-








  18  1   "SELECT DISTINCT c1, c2 FROM t3"
  19  1   "SELECT DISTINCT c1 FROM t3"
  20  1   "SELECT DISTINCT * FROM t3"
  21  0   "SELECT DISTINCT c2 FROM t3"

  22  0   "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
  23  1   "SELECT DISTINCT rowid FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"

  24  0   "SELECT DISTINCT rowid/2 FROM t1"
  25  1   "SELECT DISTINCT rowid/2, rowid FROM t1"
  26.1  0   "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?"
  26.2  1   "SELECT DISTINCT rowid/2, b FROM t4 WHERE c = ?"
} {
  if {$noop} {
289
290
291
292
293
294
295
296









297
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304








+
+
+
+
+
+
+
+
+

  WITH t2(b) AS (
    SELECT DISTINCT y FROM t5 ORDER BY y
  )
  SELECT * FROM 
    t4 CROSS JOIN t3 CROSS JOIN t1 
  WHERE (t1.a=t3.a) AND (SELECT count(*) FROM t2 AS y WHERE t4.x!='abc')=t1.a
} {2 2 2}

# 2021-04-06 forum post https://sqlite.org/forum/forumpost/66954e9ece
reset_db
do_execsql_test 8.0 {
  CREATE TABLE person ( pid INT) ;
  CREATE UNIQUE INDEX idx ON person ( pid ) WHERE pid == 1;
  INSERT INTO person VALUES (1), (10), (10);
  SELECT DISTINCT pid FROM person where pid = 10;
} {10}

finish_test
Changes to test/distinctagg.test.
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
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







+















-
+







# focus of this script is the DISTINCT modifier on aggregate functions.
#
# $Id: distinctagg.test,v 1.3 2009/02/09 13:19:28 drh Exp $


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix distinctagg

do_test distinctagg-1.1 {
  execsql {
    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    INSERT INTO t1 VALUES(1,3,4);
    INSERT INTO t1 VALUES(1,3,5);
    SELECT count(distinct a),
           count(distinct b),
           count(distinct c),
           count(all a) FROM t1;
  }
} {1 2 3 3}
do_test distinctagg-1.2 {
  execsql {
    SELECT b, count(distinct c) FROM t1 GROUP BY b ORDER BY b
    SELECT b, count(distinct c) FROM t1 GROUP BY b
  }
} {2 1 3 2}
do_test distinctagg-1.3 {
  execsql {
    INSERT INTO t1 SELECT a+1, b+3, c+5 FROM t1;
    INSERT INTO t1 SELECT a+2, b+6, c+10 FROM t1;
    INSERT INTO t1 SELECT a+4, b+12, c+20 FROM t1;
54
55
56
57
58
59
60
61

























































































































































62

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








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
  }
} {1 {DISTINCT aggregates must have exactly one argument}}
do_test distinctagg-2.2 {
  catchsql {
    SELECT group_concat(distinct a,b) FROM t1;
  }
} {1 {DISTINCT aggregates must have exactly one argument}}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);

  INSERT INTO t1 VALUES (1, 1, 1);
  INSERT INTO t1 VALUES (2, 2, 2);
  INSERT INTO t1 VALUES (3, 3, 3);
  INSERT INTO t1 VALUES (4, 1, 4);
  INSERT INTO t1 VALUES (5, 2, 1);
  INSERT INTO t1 VALUES (5, 3, 2);
  INSERT INTO t1 VALUES (4, 1, 3);
  INSERT INTO t1 VALUES (3, 2, 4);
  INSERT INTO t1 VALUES (2, 3, 1);
  INSERT INTO t1 VALUES (1, 1, 2);

  INSERT INTO t2 VALUES('a', 'a', 'a');
  INSERT INTO t2 VALUES('b', 'b', 'b');
  INSERT INTO t2 VALUES('c', 'c', 'c');

  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1bc ON t1(b, c);
}

foreach {tn use_eph sql res} {
  1  0  "SELECT count(DISTINCT a) FROM t1"                5
  2  0  "SELECT count(DISTINCT b) FROM t1"                3
  3  1  "SELECT count(DISTINCT c) FROM t1"                4
  4  0  "SELECT count(DISTINCT c) FROM t1 WHERE b=3"      3
  5  0  "SELECT count(DISTINCT rowid) FROM t1"           10
  6  0  "SELECT count(DISTINCT a) FROM t1, t2"            5
  7  0  "SELECT count(DISTINCT a) FROM t2, t1"            5
  8  1  "SELECT count(DISTINCT a+b) FROM t1, t2, t2, t2"  6
  9  0  "SELECT count(DISTINCT c) FROM t1 WHERE c=2"      1
 10  1  "SELECT count(DISTINCT t1.rowid) FROM t1, t2"    10
} {
  do_test 3.$tn.1 {
    set prg [db eval "EXPLAIN $sql"]
    set idx [lsearch $prg OpenEphemeral]
    expr {$idx>=0}
  } $use_eph

  do_execsql_test 3.$tn.2 $sql $res
}

do_execsql_test 3.10 {
  SELECT a, count(DISTINCT b) FROM t1 GROUP BY a;
} {
  1 1  2 2  3 2  4 1  5 2
}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1bc ON t1(b, c);

  INSERT INTO t1 VALUES(1, 'A', 1);
  INSERT INTO t1 VALUES(1, 'A', 1);
  INSERT INTO t1 VALUES(2, 'A', 2);
  INSERT INTO t1 VALUES(2, 'A', 2);
  INSERT INTO t1 VALUES(1, 'B', 1);
  INSERT INTO t1 VALUES(2, 'B', 2);
  INSERT INTO t1 VALUES(3, 'B', 3);
  INSERT INTO t1 VALUES(NULL, 'B', NULL);
  INSERT INTO t1 VALUES(NULL, 'C', NULL);
  INSERT INTO t1 VALUES('d', 'D', 'd');

  CREATE TABLE t2(d, e, f);
  CREATE INDEX t2def ON t2(d, e, f);

  INSERT INTO t2 VALUES(1, 1, 'a');
  INSERT INTO t2 VALUES(1, 1, 'a');
  INSERT INTO t2 VALUES(1, 2, 'a');
  INSERT INTO t2 VALUES(1, 2, 'a');
  INSERT INTO t2 VALUES(1, 2, 'b');
  INSERT INTO t2 VALUES(1, 3, 'b');
  INSERT INTO t2 VALUES(1, 3, 'a');
  INSERT INTO t2 VALUES(1, 3, 'b');
  INSERT INTO t2 VALUES(2, 3, 'x');
  INSERT INTO t2 VALUES(2, 3, 'y');
  INSERT INTO t2 VALUES(2, 3, 'z');

  CREATE TABLE t3(x, y, z);
  INSERT INTO t3 VALUES(1,1,1);
  INSERT INTO t3 VALUES(2,2,2);
}

foreach {tn use_eph sql res} {
  1 0  "SELECT count(DISTINCT c) FROM t1 GROUP BY b"   {2 3 0 1}
  2 1  "SELECT count(DISTINCT a) FROM t1 GROUP BY b"   {2 3 0 1}
  3 1  "SELECT count(DISTINCT a) FROM t1 GROUP BY b+c" {0 1 1 1 1}

  4 0  "SELECT count(DISTINCT f) FROM t2 GROUP BY d, e" {1 2 2 3}
  5 1  "SELECT count(DISTINCT f) FROM t2 GROUP BY d" {2 3}
  6 0  "SELECT count(DISTINCT f) FROM t2 WHERE d IS 1 GROUP BY e" {1 2 2}
} {
  do_test 4.$tn.1 {
    set prg [db eval "EXPLAIN $sql"]
    set idx [lsearch $prg OpenEphemeral]
    expr {$idx>=0}
  } $use_eph

  do_execsql_test 4.$tn.2 $sql $res
}


set t3root [db one {SELECT rootpage FROM sqlite_schema WHERE name='t3'}]
foreach {tn use_t3 sql res} {
  1 1 "SELECT count(*) FROM t3"   2
  2 0 "SELECT count(*) FROM t1"   10
  2 1 "SELECT count(DISTINCT a) FROM t1, t3" 4
  3 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3" 4
  4 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 4
  5 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
  6 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 ON (t3.x=0)"  4
  7 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3" 2
  8 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 1
  9 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
 10 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 ON (t3.x=0)"  0

} {
  do_test 5.$tn.1 {
    set bUse 0
    db eval "EXPLAIN $sql" a {
      if {$a(opcode)=="OpenRead" && $a(p2)==$t3root} {set bUse 1}
    }
    set bUse
  } $use_t3

  do_execsql_test 5.$tn.2 $sql $res
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
  INSERT INTO t1 VALUES(123,456);
  INSERT INTO t2 VALUES(123,456);
}
do_execsql_test 6.1 {
  SELECT count(DISTINCT c) FROM t1 LEFT JOIN t2;
} {1}

do_execsql_test 7.0 {
  CREATE TABLE v1 ( v2 UNIQUE, v3 AS( TYPEOF ( NULL ) ) UNIQUE ); 
  SELECT COUNT ( DISTINCT TRUE ) FROM v1 GROUP BY likelihood ( v3 , 0.100000 );
}


finish_test

Changes to test/e_createtable.test.
1389
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399

1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398

1399
1400
1401

1402
1403
1404
1405
1406
1407
1408
1409







-
+


-
+


-
+







#
do_execsql_test 4.10.0 {
  CREATE TABLE t1(a, b PRIMARY KEY);
  CREATE TABLE t2(a, b, c, UNIQUE(b, c));
}
do_createtable_tests 4.10 {
  1    "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" 
       {/*SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}
       {/*SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}

  2    "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
       {/*SCAN TABLE t2 USING INDEX sqlite_autoindex_t2_1*/}
       {/*SCAN t2 USING INDEX sqlite_autoindex_t2_1*/}

  3    "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
       {/*SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
       {/*SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
}

# EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
# column definition or specified as a table constraint. In practice it
# makes no difference.
#
#   All the tests that deal with CHECK constraints below (4.11.* and 
Changes to test/e_fkey.test.
988
989
990
991
992
993
994
995
996


997
998
999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009
1010
988
989
990
991
992
993
994


995
996
997
998
999
1000
1001


1002
1003
1004
1005
1006
1007
1008
1009
1010







-
-
+
+





-
-
+
+







  }
} {}
do_detail_test e_fkey-25.2 {
  PRAGMA foreign_keys = OFF;
  EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
  EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?;
} {
  {SCAN TABLE artist} 
  {SCAN TABLE track}
  {SCAN artist} 
  {SCAN track}
}
do_detail_test e_fkey-25.3 {
  PRAGMA foreign_keys = ON;
  EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
} {
  {SCAN TABLE artist} 
  {SCAN TABLE track}
  {SCAN artist} 
  {SCAN track}
}
do_test e_fkey-25.4 {
  execsql {
    INSERT INTO artist VALUES(5, 'artist 5');
    INSERT INTO artist VALUES(6, 'artist 6');
    INSERT INTO artist VALUES(7, 'artist 7');
    INSERT INTO track VALUES(1, 'track 1', 5);
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122



1123
1124
1125
1126
1127
1128


1129
1130
1131
1132
1133
1134
1135
1113
1114
1115
1116
1117
1118
1119



1120
1121
1122
1123
1124
1125
1126


1127
1128
1129
1130
1131
1132
1133
1134
1135







-
-
-
+
+
+




-
-
+
+







} {}
do_test e_fkey-27.2 {
  eqp { INSERT INTO artist VALUES(?, ?) }
} {}
do_detail_test e_fkey-27.3 {
  EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ?
} {
  {SCAN TABLE artist} 
  {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)} 
  {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
  {SCAN artist} 
  {SEARCH track USING COVERING INDEX trackindex (trackartist=?)} 
  {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}
do_detail_test e_fkey-27.4 {
  EXPLAIN QUERY PLAN DELETE FROM artist
} {
  {SCAN TABLE artist} 
  {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
  {SCAN artist} 
  {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}

###########################################################################
### SECTION 4.1: Composite Foreign Key Constraints
###########################################################################

#-------------------------------------------------------------------------
Changes to test/eqp.test.
42
43
44
45
46
47
48
49

50
51
52


53
54
55
56
57
58

59
60
61

62
63

64
65
66
67
68
69

70
71
72
73
74
75

76
77
78
79
80
81
82

83
84
85
86
87
88

89
90
91
92
93

94
95
96
97

98
99
100

101




















102
103
104
105
106

107
108
109
110
111
112
113

114
115
116

117
118
119

120
121
122
123
124
125
126



127
128
129

130
131
132

133
134
135
136
137
138
139



140
141
142
143

144
145
146

147
148
149
150
151
152
153



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176

177
178
179
180
181
182

183
184
185
186
187
188


189
190
191
192
193
194


195
196
197
198
199
200
201


202
203
204
205
206

207
208
209
210

211
212
213
214

215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231

232
233

234
235
236
237
238
239

240
241

242
243
244
245
246
247

248
249

250
251
252
253
254
255
256

257
258

259
260
261
262
263
264
265
266


267
268
269
270
271
272
273
274
275
276
277
278
279


280
281
282
283
284




285
286
287
288
289
290
291
292

293
294

295
296
297
298
299
300

301
302

303
304
305
306
307
308

309
310

311
312
313
314
315
316
317
318
319
320
321
322

323
324

325
326
327
328
329
330
331
332

333
334
335

336
337
338
339
340
341
342
343
344

345
346
347

348
349
350
351
352
353
354
355
356

357
358
359

360
361
362
363
364
365
366
367
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

482
483
484
485

486
487
488
489
490

491
492
493
494

495
496
497
498
499
500


501
502
503
504
505


506
507
508
509
510
511


512
513
514
515


516
517
518
519
520
521


522
523
524
525
526


527
528
529
530
531

532
533
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
583


584
585
586
587


588
589
590
591
592
593


594
595
596
597
598


599
600
601
602
603
604
605


606
607
608
609
610


611
612
613
614
615
616
617
42
43
44
45
46
47
48

49
50


51
52
53
54
55
56
57

58
59
60

61
62

63
64
65
66
67
68

69
70
71
72
73
74

75
76
77
78
79
80
81

82
83
84
85
86
87

88
89
90
91
92

93
94
95
96

97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132

133
134
135

136
137
138

139
140
141
142
143



144
145
146
147
148

149
150
151

152
153
154
155
156



157
158
159
160
161
162

163
164
165

166
167
168
169
170



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195

196
197
198
199
200
201

202
203
204
205
206


207
208
209
210
211
212


213
214
215
216
217
218
219


220
221
222
223
224
225

226
227
228
229

230
231
232
233

234
235
236
237
238

239
240
241
242
243
244
245
246
247
248
249
250

251
252

253
254
255
256
257
258

259
260

261
262
263
264
265
266

267
268

269
270
271
272
273
274
275

276
277

278
279
280
281
282
283
284


285
286
287
288
289
290
291
292
293
294
295
296
297


298
299
300




301
302
303
304
305
306
307
308
309
310
311

312
313

314
315
316
317
318
319

320
321

322
323
324
325
326
327

328
329

330
331
332
333
334
335
336
337
338
339
340
341

342
343

344
345
346
347
348
349
350
351

352
353
354

355
356
357
358
359
360
361
362
363

364
365
366

367
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
482
483
484
485
486
487
488
489
490
491

492
493
494
495

496
497
498
499
500

501
502
503
504

505
506
507
508
509

510
511
512
513

514
515
516
517
518


519
520
521
522
523


524
525
526
527
528
529


530
531
532
533


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

583
584
585
586
587

588
589
590
591
592
593
594

595
596
597
598
599
600
601


602
603
604
605


606
607
608
609
610
611


612
613
614
615
616


617
618
619
620
621
622
623


624
625
626
627
628


629
630
631
632
633
634
635
636
637







-
+

-
-
+
+





-
+


-
+

-
+





-
+





-
+






-
+





-
+




-
+



-
+


-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+




-
+






-
+


-
+


-
+




-
-
-
+
+
+


-
+


-
+




-
-
-
+
+
+



-
+


-
+




-
-
-
+
+
+















-
+






-
+





-
+




-
-
+
+




-
-
+
+





-
-
+
+




-
+



-
+



-
+




-
+











-
+

-
+





-
+

-
+





-
+

-
+






-
+

-
+






-
-
+
+











-
-
+
+

-
-
-
-
+
+
+
+







-
+

-
+





-
+

-
+





-
+

-
+











-
+

-
+







-
+


-
+








-
+


-
+








-
+


-
+








-
+


-
+









-
+


-
+







-
+


-
+








-
+


-
+








-
+


-
+









-
+

-
+








-
+

-
+

-
+









-
+


-
+

-
+












-
+



-
+




-
+



-
+




-
+



-
+




-
-
+
+



-
-
+
+




-
-
+
+


-
-
+
+




-
-
+
+



-
-
+
+




-
+



-
+





-
+



-
+




-
+

-
+

-
+




-
+

-
+

-
+




-
+






-
+






-
-
+
+


-
-
+
+




-
-
+
+



-
-
+
+





-
-
+
+



-
-
+
+








do_eqp_test 1.2 {
  SELECT * FROM t2, t1 WHERE t1.a=1 OR t1.b=2;
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t1 USING INDEX i1 (a=?)
  |  |  `--SEARCH t1 USING INDEX i1 (a=?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t1 USING INDEX i2 (b=?)
  `--SCAN TABLE t2
  |     `--SEARCH t1 USING INDEX i2 (b=?)
  `--SCAN t2
}
do_eqp_test 1.3 {
  SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=1 OR t1.b=2;
} {
  QUERY PLAN
  |--SCAN TABLE t2
  |--SCAN t2
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t1 USING INDEX i1 (a=?)
     |  `--SEARCH t1 USING INDEX i1 (a=?)
     `--INDEX 2
        `--SEARCH TABLE t1 USING INDEX i2 (b=?)
        `--SEARCH t1 USING INDEX i2 (b=?)
}
do_eqp_test 1.3 {
  SELECT a FROM t1 ORDER BY a
} {
  QUERY PLAN
  `--SCAN TABLE t1 USING COVERING INDEX i1
  `--SCAN t1 USING COVERING INDEX i1
}
do_eqp_test 1.4 {
  SELECT a FROM t1 ORDER BY +a
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX i1
  |--SCAN t1 USING COVERING INDEX i1
  `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 1.5 {
  SELECT a FROM t1 WHERE a=4
} {
  QUERY PLAN
  `--SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)
  `--SEARCH t1 USING COVERING INDEX i1 (a=?)
}
do_eqp_test 1.6 {
  SELECT DISTINCT count(*) FROM t3 GROUP BY a;
} {
  QUERY PLAN
  |--SCAN TABLE t3
  |--SCAN t3
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR DISTINCT
}

do_eqp_test 1.7 {
do_eqp_test 1.7.1 {
  SELECT * FROM t3 JOIN (SELECT 1)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE SUBQUERY xxxxxx
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  `--SCAN t3
}
do_eqp_test 1.7.2 {
  SELECT * FROM t3 JOIN (SELECT 1) AS v1
} {
  QUERY PLAN
  |--MATERIALIZE v1
  |  `--SCAN CONSTANT ROW
  |--SCAN v1
  `--SCAN t3
}
do_eqp_test 1.7.3 {
  SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy
} {
  QUERY PLAN
  |--MATERIALIZE yy
  |  `--SCAN CONSTANT ROW
  |--SCAN yy
  `--SCAN xx
}


do_eqp_test 1.8 {
  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE SUBQUERY xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION USING TEMP B-TREE
  |        `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  `--SCAN t3
}
do_eqp_test 1.9 {
  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--EXCEPT USING TEMP B-TREE
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  |        `--SCAN t3
  |--SCAN abc
  `--SCAN t3
}
do_eqp_test 1.10 {
  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--INTERSECT USING TEMP B-TREE
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  |        `--SCAN t3
  |--SCAN abc
  `--SCAN t3
}

do_eqp_test 1.11 {
  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17) abc
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION ALL
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
  |        `--SCAN t3
  |--SCAN abc
  `--SCAN t3
}

#-------------------------------------------------------------------------
# Test cases eqp-2.* - tests for single select statements.
#
drop_all_tables
do_execsql_test 2.1 {
  CREATE TABLE t1(x INT, y INT, ex TEXT);

  CREATE TABLE t2(x INT, y INT, ex TEXT);
  CREATE INDEX t2i1 ON t2(x);
}

det 2.2.1 "SELECT DISTINCT min(x), max(x) FROM t1 GROUP BY x ORDER BY 1" {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  |--USE TEMP B-TREE FOR GROUP BY
  |--USE TEMP B-TREE FOR DISTINCT
  `--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.2 "SELECT DISTINCT min(x), max(x) FROM t2 GROUP BY x ORDER BY 1" {
  QUERY PLAN
  |--SCAN TABLE t2 USING COVERING INDEX t2i1
  |--SCAN t2 USING COVERING INDEX t2i1
  |--USE TEMP B-TREE FOR DISTINCT
  `--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.3 "SELECT DISTINCT * FROM t1" {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN TABLE t2
  |--SCAN t1
  |--SCAN t2
  `--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.5 "SELECT DISTINCT * FROM t1, t2 ORDER BY t1.x" {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN TABLE t2
  |--SCAN t1
  |--SCAN t2
  |--USE TEMP B-TREE FOR DISTINCT
  `--USE TEMP B-TREE FOR ORDER BY
}
det 2.2.6 "SELECT DISTINCT t2.x FROM t1, t2 ORDER BY t2.x" {
  QUERY PLAN
  |--SCAN TABLE t2 USING COVERING INDEX t2i1
  `--SCAN TABLE t1
  |--SCAN t2 USING COVERING INDEX t2i1
  `--SCAN t1
}

det 2.3.1 "SELECT max(x) FROM t2" {
  QUERY PLAN
  `--SEARCH TABLE t2 USING COVERING INDEX t2i1
  `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.2 "SELECT min(x) FROM t2" {
  QUERY PLAN
  `--SEARCH TABLE t2 USING COVERING INDEX t2i1
  `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.3 "SELECT min(x), max(x) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2 USING COVERING INDEX t2i1
  `--SCAN t2 USING COVERING INDEX t2i1
}

det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
  QUERY PLAN
  `--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
}



#-------------------------------------------------------------------------
# Test cases eqp-3.* - tests for select statements that use sub-selects.
#
do_eqp_test 3.1.1 {
  SELECT (SELECT x FROM t1 AS sub) FROM t1;
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--SCAN TABLE t1 AS sub
     `--SCAN sub
}
do_eqp_test 3.1.2 {
  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--SCAN TABLE t1 AS sub
     `--SCAN sub
}
do_eqp_test 3.1.3 {
  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub ORDER BY y);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     |--SCAN TABLE t1 AS sub
     |--SCAN sub
     `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 3.1.4 {
  SELECT * FROM t1 WHERE (SELECT x FROM t2 ORDER BY x);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--SCALAR SUBQUERY xxxxxx
     `--SCAN TABLE t2 USING COVERING INDEX t2i1
     `--SCAN t2 USING COVERING INDEX t2i1
}

det 3.2.1 {
  SELECT * FROM (SELECT * FROM t1 ORDER BY x LIMIT 10) ORDER BY y LIMIT 5
} {
  QUERY PLAN
  |--CO-ROUTINE xxxxxx
  |  |--SCAN TABLE t1
  |--CO-ROUTINE SUBQUERY xxxxxx
  |  |--SCAN t1
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--SCAN SUBQUERY xxxxxx
  `--USE TEMP B-TREE FOR ORDER BY
}
det 3.2.2 {
  SELECT * FROM 
    (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
    (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
  ORDER BY x2.y LIMIT 5
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--SCAN TABLE t1
  |--MATERIALIZE x1
  |  |--SCAN t1
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--MATERIALIZE xxxxxx
  |  `--SCAN TABLE t2 USING INDEX t2i1
  |--SCAN SUBQUERY xxxxxx AS x1
  |--SCAN SUBQUERY xxxxxx AS x2
  |--MATERIALIZE x2
  |  `--SCAN t2 USING INDEX t2i1
  |--SCAN x1
  |--SCAN x2
  `--USE TEMP B-TREE FOR ORDER BY
}

det 3.3.1 {
  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2)
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--LIST SUBQUERY xxxxxx
     `--SCAN TABLE t2
     `--SCAN t2
}
det 3.3.2 {
  SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--CORRELATED LIST SUBQUERY xxxxxx
     `--SCAN TABLE t2
     `--SCAN t2
}
det 3.3.3 {
  SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x)
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     `--SCAN TABLE t2
     `--SCAN t2
}

#-------------------------------------------------------------------------
# Test cases eqp-4.* - tests for composite select statements.
#
do_eqp_test 4.1.1 {
  SELECT * FROM t1 UNION ALL SELECT * FROM t2
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  `--SCAN TABLE t1
     |  `--SCAN t1
     `--UNION ALL
        `--SCAN TABLE t2
        `--SCAN t2
}
do_eqp_test 4.1.2 {
  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 2
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2
        |--SCAN t2
        `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.3 {
  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 2
} {
  QUERY PLAN
  `--MERGE (UNION)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2
        |--SCAN t2
        `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.4 {
  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 2
} {
  QUERY PLAN
  `--MERGE (INTERSECT)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2
        |--SCAN t2
        `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test 4.1.5 {
  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 2
} {
  QUERY PLAN
  `--MERGE (EXCEPT)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2
        |--SCAN t2
        `--USE TEMP B-TREE FOR ORDER BY
}

do_eqp_test 4.2.2 {
  SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY 1
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        `--SCAN TABLE t2 USING INDEX t2i1
        `--SCAN t2 USING INDEX t2i1
}
do_eqp_test 4.2.3 {
  SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY 1
} {
  QUERY PLAN
  `--MERGE (UNION)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2 USING INDEX t2i1
        |--SCAN t2 USING INDEX t2i1
        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.4 {
  SELECT * FROM t1 INTERSECT SELECT * FROM t2 ORDER BY 1
} {
  QUERY PLAN
  `--MERGE (INTERSECT)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2 USING INDEX t2i1
        |--SCAN t2 USING INDEX t2i1
        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}
do_eqp_test 4.2.5 {
  SELECT * FROM t1 EXCEPT SELECT * FROM t2 ORDER BY 1
} {
  QUERY PLAN
  `--MERGE (EXCEPT)
     |--LEFT
     |  |--SCAN TABLE t1
     |  |--SCAN t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE t2 USING INDEX t2i1
        |--SCAN t2 USING INDEX t2i1
        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_eqp_test 4.3.1 {
  SELECT x FROM t1 UNION SELECT x FROM t2
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  `--SCAN TABLE t1
     |  `--SCAN t1
     `--UNION USING TEMP B-TREE
        `--SCAN TABLE t2 USING COVERING INDEX t2i1
        `--SCAN t2 USING COVERING INDEX t2i1
}

do_eqp_test 4.3.2 {
  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  `--SCAN TABLE t1
     |  `--SCAN t1
     |--UNION USING TEMP B-TREE
     |  `--SCAN TABLE t2 USING COVERING INDEX t2i1
     |  `--SCAN t2 USING COVERING INDEX t2i1
     `--UNION USING TEMP B-TREE
        `--SCAN TABLE t1
        `--SCAN t1
}
do_eqp_test 4.3.3 {
  SELECT x FROM t1 UNION SELECT x FROM t2 UNION SELECT x FROM t1 ORDER BY 1
} {
  QUERY PLAN
  `--MERGE (UNION)
     |--LEFT
     |  `--MERGE (UNION)
     |     |--LEFT
     |     |  |--SCAN TABLE t1
     |     |  |--SCAN t1
     |     |  `--USE TEMP B-TREE FOR ORDER BY
     |     `--RIGHT
     |        `--SCAN TABLE t2 USING COVERING INDEX t2i1
     |        `--SCAN t2 USING COVERING INDEX t2i1
     `--RIGHT
        |--SCAN TABLE t1
        |--SCAN t1
        `--USE TEMP B-TREE FOR ORDER BY
}

if 0 {
#-------------------------------------------------------------------------
# This next block of tests verifies that the examples on the 
# lang_explain.html page are correct.
#
drop_all_tables

# XVIDENCE-OF: R-47779-47605 sqlite> EXPLAIN QUERY PLAN SELECT a, b
# FROM t1 WHERE a=1;
# 0|0|0|SCAN TABLE t1
# 0|0|0|SCAN t1
#
do_execsql_test 5.1.0 { CREATE TABLE t1(a INT, b INT, ex TEXT) }
det 5.1.1 "SELECT a, b FROM t1 WHERE a=1" {
  0 0 0 {SCAN TABLE t1}
  0 0 0 {SCAN t1}
}

# XVIDENCE-OF: R-55852-17599 sqlite> CREATE INDEX i1 ON t1(a);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
# 0|0|0|SEARCH TABLE t1 USING INDEX i1
# 0|0|0|SEARCH t1 USING INDEX i1
#
do_execsql_test 5.2.0 { CREATE INDEX i1 ON t1(a) }
det 5.2.1 "SELECT a, b FROM t1 WHERE a=1" {
  0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
  0 0 0 {SEARCH t1 USING INDEX i1 (a=?)}
}

# XVIDENCE-OF: R-21179-11011 sqlite> CREATE INDEX i2 ON t1(a, b);
# sqlite> EXPLAIN QUERY PLAN SELECT a, b FROM t1 WHERE a=1;
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
#
do_execsql_test 5.3.0 { CREATE INDEX i2 ON t1(a, b) }
det 5.3.1 "SELECT a, b FROM t1 WHERE a=1" {
  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
}

# XVIDENCE-OF: R-09991-48941 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t1, t2 WHERE t1.a=1 AND t1.b>2;
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
# 0|1|1|SCAN TABLE t2
# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
# 0|1|1|SCAN t2
#
do_execsql_test 5.4.0 {CREATE TABLE t2(c INT, d INT, ex TEXT)}
det 5.4.1 "SELECT t1.a, t2.c FROM t1, t2 WHERE t1.a=1 AND t1.b>2" {
  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
  0 1 1 {SCAN TABLE t2}
  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
  0 1 1 {SCAN t2}
}

# XVIDENCE-OF: R-33626-61085 sqlite> EXPLAIN QUERY PLAN
# SELECT t1.*, t2.* FROM t2, t1 WHERE t1.a=1 AND t1.b>2;
# 0|0|1|SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)
# 0|1|0|SCAN TABLE t2
# 0|0|1|SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)
# 0|1|0|SCAN t2
#
det 5.5 "SELECT t1.a, t2.c FROM t2, t1 WHERE t1.a=1 AND t1.b>2" {
  0 0 1 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=? AND b>?)}
  0 1 0 {SCAN TABLE t2}
  0 0 1 {SEARCH t1 USING COVERING INDEX i2 (a=? AND b>?)}
  0 1 0 {SCAN t2}
}

# XVIDENCE-OF: R-04002-25654 sqlite> CREATE INDEX i3 ON t1(b);
# sqlite> EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=1 OR b=2;
# 0|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
# 0|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
do_execsql_test 5.5.0 {CREATE INDEX i3 ON t1(b)}
det 5.6.1 "SELECT a, b FROM t1 WHERE a=1 OR b=2" {
  0 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
  0 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}

# XVIDENCE-OF: R-24577-38891 sqlite> EXPLAIN QUERY PLAN
# SELECT c, d FROM t2 ORDER BY c;
# 0|0|0|SCAN TABLE t2
# 0|0|0|SCAN t2
# 0|0|0|USE TEMP B-TREE FOR ORDER BY
#
det 5.7 "SELECT c, d FROM t2 ORDER BY c" {
  0 0 0 {SCAN TABLE t2}
  0 0 0 {SCAN t2}
  0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}

# XVIDENCE-OF: R-58157-12355 sqlite> CREATE INDEX i4 ON t2(c);
# sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
# 0|0|0|SCAN TABLE t2 USING INDEX i4
# 0|0|0|SCAN t2 USING INDEX i4
#
do_execsql_test 5.8.0 {CREATE INDEX i4 ON t2(c)}
det 5.8.1 "SELECT c, d FROM t2 ORDER BY c" {
  0 0 0 {SCAN TABLE t2 USING INDEX i4}
  0 0 0 {SCAN t2 USING INDEX i4}
}

# XVIDENCE-OF: R-13931-10421 sqlite> EXPLAIN QUERY PLAN SELECT
# (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
# 0|0|0|SCAN TABLE t2
# 0|0|0|SCAN t2
# 0|0|0|EXECUTE SCALAR SUBQUERY 1
# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
# 1|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
# 2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
# 2|0|0|SEARCH t1 USING INDEX i3 (b=?)
#
det 5.9 {
  SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2
} {
  0 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
  0 0 0 {SCAN t2 USING COVERING INDEX i4}
  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
  1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
  1 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
  2 0 0 {SEARCH TABLE t1 USING INDEX i3 (b=?)}
  2 0 0 {SEARCH t1 USING INDEX i3 (b=?)}
}

# XVIDENCE-OF: R-50892-45943 sqlite> EXPLAIN QUERY PLAN
# SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
# 1|0|0|SCAN t1 USING COVERING INDEX i2
# 0|0|0|SCAN SUBQUERY 1
# 0|0|0|USE TEMP B-TREE FOR GROUP BY
#
det 5.10 {
  SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
} {
  1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
  1 0 0 {SCAN t1 USING COVERING INDEX i2}
  0 0 0 {SCAN SUBQUERY 1}
  0 0 0 {USE TEMP B-TREE FOR GROUP BY}
}

# XVIDENCE-OF: R-46219-33846 sqlite> EXPLAIN QUERY PLAN
# SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
# 0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
# 0|1|1|SCAN TABLE t1
# 0|0|0|SEARCH t2 USING INDEX i4 (c=?)
# 0|1|1|SCAN t1
#
det 5.11 "SELECT a, b FROM (SELECT * FROM t2 WHERE c=1), t1" {
  0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
  0 1 1 {SCAN TABLE t1 USING COVERING INDEX i2}
  0 0 0 {SEARCH t2 USING INDEX i4 (c=?)}
  0 1 1 {SCAN t1 USING COVERING INDEX i2}
}

# XVIDENCE-OF: R-37879-39987 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 UNION SELECT c FROM t2;
# 1|0|0|SCAN TABLE t1
# 2|0|0|SCAN TABLE t2
# 1|0|0|SCAN t1
# 2|0|0|SCAN t2
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)
#
det 5.12 "SELECT a,b FROM t1 UNION SELECT c, 99 FROM t2" {
  1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2}
  2 0 0 {SCAN TABLE t2 USING COVERING INDEX i4}
  1 0 0 {SCAN t1 USING COVERING INDEX i2}
  2 0 0 {SCAN t2 USING COVERING INDEX i4}
  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 USING TEMP B-TREE (UNION)}
}

# XVIDENCE-OF: R-44864-63011 sqlite> EXPLAIN QUERY PLAN
# SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1;
# 1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
# 2|0|0|SCAN TABLE t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
# 1|0|0|SCAN t1 USING COVERING INDEX i2
# 2|0|0|SCAN t2 2|0|0|USE TEMP B-TREE FOR ORDER BY
# 0|0|0|COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
#
det 5.13 "SELECT a FROM t1 EXCEPT SELECT d FROM t2 ORDER BY 1" {
  1 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
  2 0 0 {SCAN TABLE t2}
  1 0 0 {SCAN t1 USING COVERING INDEX i1}
  2 0 0 {SCAN t2}
  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}

if {![nonzero_reserved_bytes]} {
  #-------------------------------------------------------------------------
  # The following tests - eqp-6.* - test that the example C code on 
643
644
645
646
647
648
649
650
651


652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672

673
674
675
676
677

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696

697
698
699
700
701

702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717

718
719
720
721
722

723
724
725
726
727

728
729
730
731
732

733
734
735
736
737

738
739
740
741
742

743
744
745
746
747

748
749
750
751
752
753
754
663
664
665
666
667
668
669


670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691

692
693
694
695
696

697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715

716
717
718
719
720

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736

737
738
739
740
741

742
743
744
745
746

747
748
749
750
751

752
753
754
755
756

757
758
759
760
761

762
763
764
765
766

767
768
769
770
771
772
773
774







-
-
+
+




















-
+




-
+


















-
+




-
+















-
+




-
+




-
+




-
+




-
+




-
+




-
+







      set data
    }] [list $res]
  }
  
  do_peqp_test 6.1 {
    SELECT a, b FROM t1 EXCEPT SELECT d, 99 FROM t2 ORDER BY 1
  } [string trimleft {
1 0 0 SCAN TABLE t1 USING COVERING INDEX i2
2 0 0 SCAN TABLE t2
1 0 0 SCAN t1 USING COVERING INDEX i2
2 0 0 SCAN t2
2 0 0 USE TEMP B-TREE FOR ORDER BY
0 0 0 COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)
}]
}
}

#-------------------------------------------------------------------------
# The following tests - eqp-7.* - test that queries that use the OP_Count
# optimization return something sensible with EQP.
#
drop_all_tables

do_execsql_test 7.0 {
  CREATE TABLE t1(a INT, b INT, ex CHAR(100));
  CREATE TABLE t2(a INT, b INT, ex CHAR(100));
  CREATE INDEX i1 ON t2(a);
}

det 7.1 "SELECT count(*) FROM t1" {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}

det 7.2 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2 USING COVERING INDEX i1
  `--SCAN t2 USING COVERING INDEX i1
}

do_execsql_test 7.3 {
  INSERT INTO t1(a,b) VALUES(1, 2);
  INSERT INTO t1(a,b) VALUES(3, 4);

  INSERT INTO t2(a,b) VALUES(1, 2);
  INSERT INTO t2(a,b) VALUES(3, 4);
  INSERT INTO t2(a,b) VALUES(5, 6);
 
  ANALYZE;
}

db close
sqlite3 db test.db

det 7.4 "SELECT count(*) FROM t1" {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}

det 7.5 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2 USING COVERING INDEX i1
  `--SCAN t2 USING COVERING INDEX i1
}

#-------------------------------------------------------------------------
# The following tests - eqp-8.* - test that queries that use the OP_Count
# optimization return something sensible with EQP.
#
drop_all_tables

do_execsql_test 8.0 {
  CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
  CREATE TABLE t2(a, b, c);
}

det 8.1.1 "SELECT * FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2
  `--SCAN t2
}

det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

det 8.1.3 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2
  `--SCAN t2
}

det 8.2.1 "SELECT * FROM t1" {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}

det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (b=?)
  `--SEARCH t1 USING PRIMARY KEY (b=?)
}

det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)
  `--SEARCH t1 USING PRIMARY KEY (b=? AND c=?)
}

det 8.2.4 "SELECT count(*) FROM t1" {
  QUERY PLAN
  `--SCAN TABLE t1
  `--SCAN t1
}

# 2018-08-16:  While working on Fossil I discovered that EXPLAIN QUERY PLAN
# did not describe IN operators implemented using a ROWID lookup.  These
# test cases ensure that problem as been fixed.
#
do_execsql_test 9.0 {
810
811
812
813
814
815
816
817
818


819
820
821

822
823
824
825
826



827
828
829
830
830
831
832
833
834
835
836


837
838
839
840

841
842
843



844
845
846
847
848
849
850







-
-
+
+


-
+


-
-
-
+
+
+




    substr(event.comment,instr(event.comment,':')+1)
  FROM thread, blob, event
  WHERE blob.rid=thread.last
    AND event.objid=thread.last
  ORDER BY 1;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--SCAN TABLE forumpost AS x USING INDEX forumthread
  |--MATERIALIZE thread
  |  |--SCAN x USING INDEX forumthread
  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
  |  |--CORRELATED SCALAR SUBQUERY xxxxxx
  |  |  |--SEARCH TABLE forumpost USING COVERING INDEX forumthread (froot=?)
  |  |  |--SEARCH forumpost USING COVERING INDEX forumthread (froot=?)
  |  |  `--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--SCAN SUBQUERY xxxxxx
  |--SEARCH TABLE blob USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH TABLE event USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN thread
  |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test
Deleted test/exists2.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
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




























































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# 2021 January 15
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix exists2

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(4, 'four');
  INSERT INTO t1 VALUES(5, 'five');
  INSERT INTO t1 VALUES(6, 'six');
  INSERT INTO t1 VALUES(7, 'seven');

  CREATE TABLE t2(c INTEGER, d INTEGER);
  INSERT INTO t2 VALUES(1, 1);
  INSERT INTO t2 VALUES(3, 2);
  INSERT INTO t2 VALUES(5, 3);
  INSERT INTO t2 VALUES(7, 4);
}

proc do_execsql_eqp_test {tn sql eqp res} {
  uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]]
  uplevel [list do_execsql_test $tn.2 $sql $res]
}

do_execsql_eqp_test 1.1 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c);
} {
  USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.2 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a);
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.3 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a);
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  2 two 4 four 6 six
}

do_execsql_eqp_test 1.4 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1);
} {
  SCAN TABLE t1
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.5 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3)
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

do_execsql_eqp_test 1.6 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c 
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

do_execsql_eqp_test 1.7 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c 
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID;
  CREATE TABLE t4(c TEXT COLLATE nocase, y INT);

  INSERT INTO t3 VALUES('one', 'i', 1);
  INSERT INTO t3 VALUES('two', 'ii', 2);
  INSERT INTO t3 VALUES('three', 'iii', 3);
  INSERT INTO t3 VALUES('four', 'iv', 4);
  INSERT INTO t3 VALUES('five', 'v', 5);

  INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1);
}

do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one}
do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two}

do_execsql_eqp_test 2.3 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
  SEARCH TABLE t3 USING PRIMARY KEY
} {
  four one
}

do_execsql_eqp_test 2.4 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
  SCAN TABLE t3
} {
  five four one two
}

do_execsql_test 2.5 {
  CREATE INDEX t3anc ON t3(a COLLATE nocase, x);
}

do_execsql_eqp_test 2.6 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
  SEARCH TABLE t3 USING COVERING INDEX t3anc
} {
  five four one two
}
do_execsql_test 2.6a {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x))
} {five four one two}

do_execsql_eqp_test 2.7 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
  SEARCH TABLE t3 USING PRIMARY KEY
} {
  four one
}
do_execsql_test 2.7a {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y))
} {
  four one
}

# EXISTS clauses using vector expressions in the WHERE clause.
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888);
  CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
  INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333);
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b));
} {222}
do_execsql_test 3.1 {
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y));
} {222}
do_execsql_test 3.2 {
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y));
} {222}





finish_test
Deleted test/existsfault.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




















































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# 2021 January 15
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix existsfault

do_execsql_test 1 {
  CREATE TABLE t1(a PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(4, 'four');
  INSERT INTO t1 VALUES(5, 'five');
  INSERT INTO t1 VALUES(6, 'six');
  INSERT INTO t1 VALUES(7, 'seven');

  CREATE TABLE t2(c INTEGER, d INTEGER);
  INSERT INTO t2 VALUES(1, 1);
  INSERT INTO t2 VALUES(3, 2);
  INSERT INTO t2 VALUES(5, 3);
  INSERT INTO t2 VALUES(7, 4);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT t1.* FROM t1 WHERE EXISTS(
        SELECT * FROM t2 WHERE t2.c=t1.a AND d IN (1, 2, 3)
    )
  }
} -test {
  faultsim_test_result {0 {1 one 3 three 5 five}}
}


finish_test

Added test/exprfault.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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 April 17
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix exprfault

do_execsql_test 1.0 {
  CREATE TABLE t1(a);                 
  CREATE TABLE t2(d);                 
}
faultsim_save_and_close

do_faultsim_test 1.1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT a = ( SELECT d FROM (SELECT d FROM t2) ) FROM t1 
  }
} -test {
  faultsim_test_result {0 {}}
}


finish_test
Added test/external_reader.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# 2021 April 2
#
# 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.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix external_reader

ifcapable !wal {
  finish_test 
  return 
}
if {$::tcl_platform(platform)!="unix"} {
  finish_test 
  return
}

do_multiclient_test tn {

  set bExternal 1
  if {[info commands db3]!=""} { set bExternal 0 }

  do_test 1.$tn.0 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
    }
  } {wal}

  do_test 1.$tn.1 {
    sql2 { SELECT * FROM t1 }
  } {1 2}

  do_test 1.$tn.2 {
    code1 {
      file_control_external_reader db
    } 
  } {0}

  do_test 1.$tn.3 {
    sql2 { 
      BEGIN;
        SELECT * FROM t1;
    }
  } {1 2}

  do_test 1.$tn.4 {
    code1 {
      file_control_external_reader db
    } 
  } $bExternal

  do_test 1.$tn.5 {
    sql2 { COMMIT }
  } {}

  do_test 1.$tn.6 {
    code1 { file_control_external_reader db } 
  } 0

}


finish_test
Changes to test/fts3aux1.test.
101
102
103
104
105
106
107
108

109
110
111

112
113
114
115
116
117
118
101
102
103
104
105
106
107

108
109
110

111
112
113
114
115
116
117
118







-
+


-
+







db func rec rec

# Use EQP to show that the WHERE expression "term='braid'" uses a different
# index number (1) than "+term='braid'" (0).
#
do_execsql_test 2.1.1.1 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 1:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 1:*/}
do_execsql_test 2.1.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}

# Now show that using "term='braid'" means the virtual table returns
# only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
#
do_test 2.1.2.1 {
  set cnt 0
  execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='braid' }
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
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







-
+


-
+



-
+


-
+



-
+


-
+








# Special case: term=NULL
#
do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}

do_execsql_test 2.2.1.1 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 2:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 2:*/}
do_execsql_test 2.2.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}

do_execsql_test 2.2.1.3 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 4:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 4:*/}
do_execsql_test 2.2.1.4 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}

do_execsql_test 2.2.1.5 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 6:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 6:*/}
do_execsql_test 2.2.1.6 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
} {/*SCAN TABLE terms VIRTUAL TABLE INDEX 0:*/}
} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}

do_test 2.2.2.1 {
  set cnt 0
  execsql { SELECT * FROM terms WHERE rec('cnt', term) AND term>'brain' }
  set cnt
} {18}
do_test 2.2.2.2 {
331
332
333
334
335
336
337
338

339
340
341
342
343
344
345
331
332
333
334
335
336
337

338
339
340
341
342
343
344
345







-
+







  5    1    "ORDER BY documents"
  6    1    "ORDER BY documents DESC"
  7    1    "ORDER BY occurrences ASC"
  8    1    "ORDER BY occurrences"
  9    1    "ORDER BY occurrences DESC"
} {

  set res {SCAN TABLE terms VIRTUAL TABLE INDEX 0:}
  set res {SCAN terms VIRTUAL TABLE INDEX 0:}
  if {$sort} { append res {*USE TEMP B-TREE FOR ORDER BY} }
  set res "/*$res*/"

  set sql "SELECT * FROM terms $orderby"
  do_execsql_test 2.3.1.$tn "EXPLAIN QUERY PLAN $sql" $res
}

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
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







-
-
+
+








-
-
+
+








-
-
+
+








-
-
+
+







  do_execsql_test $tn $sql $r2
}

do_plansql_test 4.2 {
  SELECT y FROM x2, terms WHERE y = term AND col = '*'
} {
  QUERY PLAN
  |--SCAN TABLE x2
  `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
  |--SCAN x2
  `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
  a b c d e f g h i j k l
}

do_plansql_test 4.3 {
  SELECT y FROM terms, x2 WHERE y = term AND col = '*'
} {
  QUERY PLAN
  |--SCAN TABLE x2
  `--SCAN TABLE terms VIRTUAL TABLE INDEX 1:
  |--SCAN x2
  `--SCAN terms VIRTUAL TABLE INDEX 1:
} {
  a b c d e f g h i j k l
}

do_plansql_test 4.4 {
  SELECT y FROM x3, terms WHERE y = term AND col = '*'
} {
  QUERY PLAN
  |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
  `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
  |--SCAN terms VIRTUAL TABLE INDEX 0:
  `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
  a b c d e f g h i j k l
}

do_plansql_test 4.5 {
  SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
} {
  QUERY PLAN
  |--SCAN TABLE terms VIRTUAL TABLE INDEX 0:
  `--SEARCH TABLE x3 USING COVERING INDEX i1 (y=?)
  |--SCAN terms VIRTUAL TABLE INDEX 0:
  `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
  a k l
}

#-------------------------------------------------------------------------
# The following tests check that fts4aux can handle an fts table with an
# odd name (one that requires quoting for use in SQL statements). And that
Changes to test/fts3corrupt4.test.
6380
6381
6382
6383
6384
6385
6386











































































































































































































6387
6388
6389
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



| end sql038051.txt.db
}]} {}

do_catchsql_test 48.1 {
  INSERT INTO x1(x1) VALUES('nodesize=24'),('merge=3,4');
  INSERT INTO x1(x1) VALUES( 'merge=3,4' ),('merge=3,4');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 49.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-58821b8eae6883.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04   ................
|     96: 00 00 00 00 0d 0e ef 00 07 0d 4d 00 0f bd 0f 5f   ..........M...._
|    112: 0e f7 0e 06 0e bc 0d a4 0d 4d 00 00 00 00 00 00   .........M......
|   3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 55 07 07   .............U..
|   3408: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 73 74   ......tablet1_st
|   3424: 61 74 74 31 5f 73 74 61 74 07 43 52 45 41 54 45   att1_stat.CREATE
|   3440: 20 54 41 42 4c 45 20 27 74 31 5f 73 74 61 74 27    TABLE 't1_stat'
|   3456: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   (id INTEGER PRIM
|   3472: 41 52 59 20 4b 45 59 2c 20 76 61 6c 75 65 20 42   ARY KEY, value B
|   3488: 4c 4f 42 29 60 06 07 17 21 21 01 81 0b 74 61 62   LOB)`...!!...tab
|   3504: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64   let1_docsizet1_d
|   3520: 6f 63 73 69 7a 65 06 43 52 45 41 54 45 20 54 41   ocsize.CREATE TA
|   3536: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27   BLE 't1_docsize'
|   3552: 28 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50   (docid INTEGER P
|   3568: 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 69 7a 65   RIMARY KEY, size
|   3584: 20 42 4c 4f 42 29 81 33 04 07 17 1f 1f 01 82 35    BLOB).3.......5
|   3600: 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72 74 31   tablet1_segdirt1
|   3616: 5f 73 65 67 64 69 72 04 43 52 45 41 54 45 20 54   _segdir.CREATE T
|   3632: 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69 72 27   ABLE 't1_segdir'
|   3648: 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52 2c 69   (level INTEGER,i
|   3664: 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61 72 74   dx INTEGER,start
|   3680: 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c   _block INTEGER,l
|   3696: 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20   eaves_end_block 
|   3712: 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63   INTEGER,end_bloc
|   3728: 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42   k INTEGER,root B
|   3744: 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45 59 28   LOB,PRIMARY KEY(
|   3760: 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 05 06 17   level, idx))1...
|   3776: 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74 65 5f   E...indexsqlite_
|   3792: 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73 65 67   autoindex_t1_seg
|   3808: 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72 05 00   dir_1t1_segdir..
|   3824: 00 00 08 00 00 00 00 66 03 07 17 23 23 01 81 13   .......f...##...
|   3840: 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e 74 73   tablet1_segments
|   3856: 74 31 5f 73 65 67 6d 65 6e 74 73 03 43 52 45 41   t1_segments.CREA
|   3872: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67   TE TABLE 't1_seg
|   3888: 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64 20 49   ments'(blockid I
|   3904: 4e 54 45 47 45 52 20 f9 52 49 4d 41 52 59 20 4b   NTEGER .RIMARY K
|   3920: 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c   EY, block BLOB).
|   3936: 02 07 17 21 21 01 81 03 74 61 62 6c 65 74 31 5f   ...!!...tablet1_
|   3952: 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 65 6e   contentt1_conten
|   3968: 74 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   t.CREATE TABLE '
|   3984: 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69   t1_content'(doci
|   4000: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52   d INTEGER PRIMAR
|   4016: 59 20 4b 45 59 2c 20 27 63 30 61 27 29 41 01 06   Y KEY, 'c0a')A..
|   4032: 17 11 11 08 71 74 61 62 6c 65 74 31 74 31 43 52   ....qtablet1t1CR
|   4048: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   4064: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 34   LE t1 USING fts4
|   4080: 28 61 2c 70 72 65 66 69 78 3d 27 32 2c 32 27 29   (a,prefix='2,2')
| page 2 offset 4096
|      0: 0d 00 00 00 08 0e 1f 00 0f c4 0f 7c 0f 34 0f 07   ...........|.4..
|     16: 0e c3 0e 97 0e 00 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42   ...............B
|   3616: 08 04 00 81 09 73 75 6e 74 20 69 6e 20 63 75 6c   .....sunt in cul
|   3632: 70 61 20 71 75 69 20 6f 66 66 69 63 69 61 20 64   pa qui officia d
|   3648: 65 73 65 72 75 6e 74 20 6d 6f 6c 6c 69 74 20 61   eserunt mollit a
|   3664: 6e 69 6d 20 69 64 20 65 73 74 20 6c 61 62 6f 72   nim id est labor
|   3680: 75 6d 2e 32 07 03 00 6b 45 78 63 65 70 74 65 75   um.2...kExcepteu
|   3696: 72 20 73 69 6e 74 20 6f 63 63 61 65 63 61 74 20   r sint occaecat 
|   3712: 63 75 70 69 64 61 74 61 74 20 6e 6f 6e 20 70 72   cupidatat non pr
|   3728: 6f 69 64 65 6e 74 2c 2a 06 03 00 5b 63 69 6c 6c   oident,*...[cill
|   3744: 75 6d 20 64 6f 6c 6f 72 65 20 65 75 20 66 75 67   um dolore eu fug
|   3760: 69 61 74 20 6e 75 6c 6c 61 20 70 61 72 69 61 74   iat nulla pariat
|   3776: 75 72 2e 42 05 04 00 81 09 44 75 69 73 20 61 75   ur.B.....Duis au
|   3792: 74 65 20 69 72 75 72 65 20 64 6f 6c 6f 72 20 69   te irure dolor i
|   3808: 6e 20 72 65 70 72 65 68 65 6e 64 65 72 69 74 20   n reprehenderit 
|   3824: 69 6e 20 76 6f 6c 75 70 74 61 74 65 20 76 65 6c   in voluptate vel
|   3840: 69 74 20 65 73 73 65 2b 04 03 00 5d 6e 69 73 69   it esse+...]nisi
|   3856: 20 75 74 20 61 6c 69 71 75 69 70 20 65 78 20 65    ut aliquip ex e
|   3872: 61 20 63 6f 6d 6d 6f 64 6f 20 63 6f 6e 73 65 71   a commodo conseq
|   3888: 75 61 74 2e 46 03 04 00 81 11 55 74 20 65 6e 69   uat.F.....Ut eni
|   3904: 6d 20 61 64 20 6d 69 6e 69 6d 20 76 65 6e 69 61   m ad minim venia
|   3920: 6d 2c 20 71 75 69 73 20 6e 6f 73 74 72 75 64 20   m, quis nostrud 
|   3936: 65 78 65 72 63 69 74 61 74 69 6f 6e 20 75 6c 6c   exercitation ull
|   3952: 61 6d 63 6f 20 6c 61 62 6f 72 69 73 46 02 04 00   amco laborisF...
|   3968: 81 11 73 65 64 20 64 6f 20 65 69 75 73 6d 6f 64   ..sed do eiusmod
|   3984: 20 74 65 6d 70 6f 72 20 69 6e 63 69 64 69 64 75    tempor incididu
|   4000: 6e 74 20 75 74 20 6c 61 62 6f 72 65 20 65 74 20   nt ut labore et 
|   4016: 64 6f 6c 6f 72 65 20 6d 61 67 6e 61 20 61 6c 69   dolore magna ali
|   4032: 71 75 61 2e 3a 01 03 00 7b 4c 6f 72 65 6d 20 69   qua.:....Lorem i
|   4048: 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61   psum dolor sit a
|   4064: 6d 65 74 2c 20 63 6f 6e 73 65 63 74 65 74 75 72   met, consectetur
|   4080: 20 61 64 69 70 69 73 63 69 6e 67 20 65 00 01 00    adipiscing e...
| page 4 offset 12288
|      0: 0d 00 00 00 03 0a a6 00 0d 57 0c 4a 0a a6 00 00   .........W.J....
|   2720: 00 00 00 00 00 00 83 21 03 08 02 08 08 08 17 86   .......!........
|   2736: 30 08 00 30 20 34 30 32 00 02 61 64 06 01 08 00   0..0 402..ad....
|   2752: 02 04 00 01 01 6c 06 02 0c 00 02 04 00 01 01 6d   .....l.........m
|   2768: 03 01 06 00 01 01 6e 03 08 09 00 01 01 75 03 05   ......n......u..
|   2784: 03 00 00 02 63 69 03 06 02 00 01 01 6f 07 01 07   ....ci......o...
|   2800: 00 03 07 03 00 01 01 75 06 07 05 00 01 04 00 00   .......u........
|   2816: 02 64 65 03 08 07 00 01 01 6f 0d 01 04 00 01 03   .de......o......
|   2832: 09 00 03 05 00 01 03 00 01 01 75 03 05 02 00 00   ..........u.....
|   2848: 02 65 61 03 04 06 00 01 01 69 03 02 04 00 01 01   .ea......i......
|   2864: 6c 03 01 09 00 01 01 6e 03 03 03 00 01 01 73 06   l......n......s.
|   2880: 05 0b 00 03 0b 00 01 01 74 03 02 09 00 01 01 75   ........t......u
|   2896: 03 06 04 00 01 01 78 09 03 09 00 01 05 00 03 02   ......x.........
|   2912: 00 00 02 66 75 03 06 05 00 00 02 69 64 03 08 0a   ...fu......id...
|   2928: 00 01 01 6e 0a 02 06 00 03 06 04 00 03 03 00 01   ...n............
|   2944: 01 70 03 01 03 00 01 01 72 03 05 04 00 00 02 6c   .p......r......l
|   2960: 61 09 02 08 00 01 0b 00 05 0c 00 01 01 6f 03 01   a............o..
|   2976: 02 00 00 02 6d 61 03 02 0b 00 01 01 69 03 03 05   ....ma......i...
|   2992: 00 01 01 6f 03 08 08 00 00 02 6e 69 03 04 02 00   ...o......ni....
|   3008: 01 01 6f 06 03 08 00 04 06 00 01 01 75 03 06 06   ..o.........u...
|   3024: 00 00 02 6f 63 03 07 04 00 01 01 66 03 08 06 00   ...oc......f....
|   3040: 00 02 70 61 03 06 07 00 01 01 72 03 07 07 00 00   ..pa......r.....
|   3056: 02 71 75 06 03 07 00 05 05 00 00 02 72 65 03 05   .qu.........re..
|   3072: 07 00 00 02 73 65 03 02 02 00 01 01 69 06 01 05   ....se......i...
|   3088: 00 06 03 00 01 01 75 03 08 02 00 00 02 74 65 03   ......u......te.
|   3104: 02 05 00 00 02 75 6c 03 03 0a 00 01 01 74 09 02   .....ul......t..
|   3120: 07 00 01 02 00 01 03 00 00 02 76 65 06 03 06 00   ..........ve....
|   3136: 02 0a 00 01 01 6f 03 05 09 00 82 0a 02 08 02 08   .....o..........
|   3152: 08 08 17 84 02 04 00 30 20 32 35 31 00 01 61 13   .......0 251..a.
|   3168: 01 06 04 00 01 0c 00 01 04 00 01 04 00 01 03 00   ................
|   3184: 03 09 00 00 01 63 10 01 07 00 03 07 03 00 02 02   .....c..........
|   3200: 00 01 05 00 01 04 00 00 01 64 11 01 04 00 01 03   .........d......
|   3216: 09 00 03 02 05 00 01 03 00 02 07 00 00 01 65 1b   ..............e.
|   3232: 01 09 00 01 04 07 00 01 03 08 00 01 05 03 00 01   ................
|   3248: 0b 00 01 04 00 01 02 00 01 0b 00 00 01 66 03 06   .............f..
|   3264: 05 00 00 01 69 0f 01 03 00 01 06 00 03 04 04 04   ....i...........
|   3280: 00 03 03 09 00 00 01 6c 0c 01 02 00 01 08 00 01   .......l........
|   3296: 0b 00 05 0c 00 00 01 6d 09 02 0b 00 01 05 00 05   .......m........
|   3312: 08 00 00 01 6e 0c 03 08 00 01 02 00 02 06 00 01   ....n...........
|   3328: 06 00 00 01 6f 06 07 04 00 01 06 00 00 01 70 06   ....o.........p.
|   3344: 06 07 00 01 07 00 00 01 71 06 03 07 00 05 05 00   ........q.......
|   3360: 00 01 72 03 05 07 00 00 01 73 0c 01 05 00 01 02   ..r......s......
|   3376: 00 05 03 00 01 02 00 00 01 74 03 02 05 00 00 01   .........t......
|   3392: 75 0a 02 07 00 01 02 0a 00 01 03 00 00 01 76 07   u.............v.
|   3408: 03 06 00 02 09 03 00 85 26 01 08 08 08 08 08 17   ........&.......
|   3424: 8a 3e 30 20 36 36 35 00 02 61 65 03 03 04 00 02   .>0 665..ae.....
|   3440: 08 69 70 69 73 63 69 6e 67 03 01 08 00 01 05 6c   .ipiscing......l
|   3456: 69 71 75 61 03 02 0c 00 05 02 69 70 03 04 04 00   iqua......ip....
|   3472: 01 03 6d 65 74 03 01 06 00 01 03 6e 69 6d 03 08   ..met......nim..
|   3488: 09 00 01 03 75 74 65 03 05 03 00 00 06 63 69 6c   ....ute......cil
|   3504: 6c 75 6d 03 06 02 00 01 06 6f 6d 6d 6f 64 6f 03   lum......ommodo.
|   3520: 04 07 00 02 09 6e 73 65 63 74 65 74 b5 72 03 01   .....nsectet.r..
|   3536: 07 00 05 04 71 75 61 74 03 04 08 00 01 04 75 6c   ....quat......ul
|   3552: 70 61 03 08 04 00 02 07 70 69 64 61 74 61 74 03   pa......pidatat.
|   3568: 07 05 00 00 08 64 65 73 65 72 75 6e 74 03 08 07   .....deserunt...
|   3584: 00 01 01 6f 03 02 03 00 02 03 6c 6f 72 06 01 04   ...o......lor...
|   3600: 00 04 05 00 05 01 65 06 02 0a 00 04 03 00 01 03   ......e.........
|   3616: 75 69 73 03 05 02 00 00 02 65 61 03 04 06 00 01   uis......ea.....
|   3632: 06 69 75 73 6d 6f 64 03 02 04 00 01 03 6c 69 74   .iusmod......lit
|   3648: 03 01 09 00 01 03 6e 69 6d 03 03 03 00 01 03 73   ......nim......s
|   3664: 73 65 03 05 0b 00 02 01 74 03 08 0b 00 01 01 74   se......t......t
|   3680: 03 02 09 00 01 01 75 03 06 04 00 01 01 78 03 04   ......u......x..
|   3696: 05 00 02 07 63 65 70 74 65 75 72 03 07 02 00 02   ....cepteur.....
|   3712: 0a 65 72 63 69 74 61 74 69 6f 6e 03 03 09 00 00   .ercitation.....
|   3728: 06 66 75 67 69 61 74 03 06 05 00 00 02 69 64 03   .fugiat......id.
|   3744: 08 0a 00 01 01 6e 07 05 06 04 00 03 03 00 02 08   .....n..........
|   3760: 63 69 64 69 64 75 6e 74 03 02 06 00 01 04 70 73   cididunt......ps
|   3776: 75 6d 03 01 03 00 01 04 72 75 72 65 03 05 04 00   um......rure....
|   3792: 00 06 6c 61 62 6f 72 65 03 02 08 00 05 02 69 73   ..labore......is
|   3808: 03 03 0b 00 05 02 75 6d 03 08 0c 00 01 04 6f 72   ......um......or
|   3824: 65 6d 03 01 02 00 00 05 6d 61 67 6e 61 03 02 0b   em......magna...
|   3840: 00 01 04 69 6e 69 6d 03 03 05 00 01 05 6f 6c 6c   ...inim......oll
|   3856: 69 74 03 08 08 00 00 04 6e 69 73 69 03 04 02 00   it......nisi....
|   3872: 01 02 6f 6e 03 07 06 00 02 05 73 74 72 75 64 03   ..on......strud.
|   3888: 03 08 00 01 04 75 6c 6c 61 03 06 06 00 00 08 6f   .....ulla......o
|   3904: 63 63 61 65 63 61 74 03 07 04 00 01 06 66 66 69   ccaecat......ffi
|   3920: 63 69 61 03 08 06 00 00 08 70 61 72 69 61 74 75   cia......pariatu
|   3936: 72 03 06 07 00 01 07 72 6f 69 64 65 6e 74 03 07   r......roident..
|   3952: 07 00 00 03 71 75 69 03 08 05 00 03 01 73 03 03   ....qui......s..
|   3968: 07 00 00 0d 72 65 70 72 65 68 65 6e 64 65 72 69   ....reprehenderi
|   3984: 74 03 05 07 00 00 03 73 65 64 03 02 02 00 01 03   t......sed......
|   4000: 69 6e 74 03 07 03 00 02 01 74 03 01 05 00 01 03   int......t......
|   4016: 75 6e 74 03 08 02 00 00 06 74 65 6d 70 6f 72 03   unt......tempor.
|   4032: 02 05 00 00 07 75 6c 6c 61 6d 63 6f 03 03 0a 00   .....ullamco....
|   4048: 01 01 74 09 02 07 00 01 02 00 01 03 00 00 05 76   ..t............v
|   4064: 65 6c 69 74 03 05 0a 00 02 04 6e 69 61 6d 03 03   elit......niam..
|   4080: 06 00 01 08 6f 6c 75 70 74 61 74 65 03 05 09 00   ....oluptate....
| page 5 offset 16384
|      0: 0a 00 00 00 03 0f eb 00 0f fb 0f f3 0f eb 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 07 04 02 08 01   ................
|   4080: 08 00 03 07 04 02 08 01 04 00 02 04 04 08 08 09   ................
| page 6 offset 20480
|      0: 0d 00 00 00 08 0f d0 00 0f fa 0f f4 0f ee 0f e8   ................
|     16: 0f e2 0f dc 0f d6 0f d0 00 00 00 00 00 00 00 00   ................
|   4048: 04 08 03 00 0e 0b 04 07 03 00 0e 06 04 06 03 00   ................
|   4064: 0e 06 04 05 03 00 0e 0a 04 04 03 00 0e 07 04 03   ................
|   4080: 03 00 0e 0a 04 02 03 00 0e 0b 04 01 03 00 0e 08   ................
| page 7 offset 24576
|      0: 0d 00 00 00 01 0f f7 00 0f f7 00 00 00 00 01 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-58821b8eae6883.db
}]} {}

do_catchsql_test 49.1 {
  SAVEPOINT one;
  DELETE FROM t1 WHERE t1 MATCH 'c*';
  SELECT matchinfo(t1,'pcx') IS NULL FROM t1 WHERE t1 MATCH 'f*e*';
} {0 0}



finish_test
Changes to test/fts3corrupt6.test.
60
61
62
63
64
65
66
67
68
60
61
62
63
64
65
66









-
-
}
do_execsql_test 2.1 {
  SELECT count(*) FROM t0 WHERE t0 MATCH '(1 NEAR 1) AND (aaaa OR 1)';
} 1

set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test


Changes to test/fts3join.test.
93
94
95
96
97
98
99
100
101
102
103




104
105
106
93
94
95
96
97
98
99




100
101
102
103
104
105
106







-
-
-
-
+
+
+
+



do_eqp_test 4.2 {
  SELECT * FROM t4 LEFT JOIN (
      SELECT docid, * FROM ft4 WHERE ft4 MATCH ?
  ) AS rr ON t4.rowid=rr.docid 
  WHERE t4.y = ?;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN TABLE ft4 VIRTUAL TABLE INDEX 3:
  |--SCAN TABLE t4
  `--SEARCH SUBQUERY xxxxxx AS rr USING AUTOMATIC COVERING INDEX (docid=?)
  |--MATERIALIZE rr
  |  `--SCAN ft4 VIRTUAL TABLE INDEX 3:
  |--SCAN t4
  `--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?)
}

finish_test
Changes to test/fts3query.test.
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
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







-
-
+
+





-
-
+
+





-
-
+
+





-
-
+
+







    CREATE TABLE bt(title);
  }
} {}
do_eqp_test fts3query-4.2 {
  SELECT t1.number FROM t1, ft WHERE t1.number=ft.rowid ORDER BY t1.date
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX i1
  `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
  |--SCAN t1 USING COVERING INDEX i1
  `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.3 {
  SELECT t1.number FROM ft, t1 WHERE t1.number=ft.rowid ORDER BY t1.date
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX i1
  `--SCAN TABLE ft VIRTUAL TABLE INDEX 1:
  |--SCAN t1 USING COVERING INDEX i1
  `--SCAN ft VIRTUAL TABLE INDEX 1:
}
do_eqp_test fts3query-4.4 {
  SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX i1
  `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 USING COVERING INDEX i1
  `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test fts3query-4.5 {
  SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX i1
  `--SEARCH TABLE bt USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1 USING COVERING INDEX i1
  `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}


# Test that calling matchinfo() with the wrong number of arguments, or with
# an invalid argument returns an error.
#
do_execsql_test 5.1 {
Changes to test/fts3snippet2.test.
53
54
55
56
57
58
59
60
53
54
55
56
57
58
59








-
do_execsql_test 2.2 {
  SELECT snippet(t0)  FROM t0 WHERE t0 MATCH 
  '(def AND (one NEAR abc)) OR one'
} {<b>one</b>}

set sqlite_fts3_enable_parentheses 0
finish_test

Changes to test/fts4upfrom.test.
133
134
135
136
137
138
139
140
133
134
135
136
137
138
139








-
    12 b apple blueberry
    13 c banana clementine
    14 d cherry dewberry
  }
}

finish_test

Changes to test/fuzzcheck.c.
932
933
934
935
936
937
938




939

940
941
942
943
944
945
946
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951







+
+
+
+

+







  }

  /* Block debug pragmas and ATTACH/DETACH.  But wait until after
  ** deserialize to do this because deserialize depends on ATTACH */
  sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0);

  /* Consistent PRNG seed */
#ifdef SQLITE_TESTCTRL_PRNG_SEED
  sqlite3_table_column_metadata(cx.db, 0, "x", 0, 0, 0, 0, 0, 0);
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, cx.db);
#else
  sqlite3_randomness(0,0);
#endif

  zSql = sqlite3_malloc( nSql + 1 );
  if( zSql==0 ){
    fprintf(stderr, "Out of memory!\n");
  }else{
    memcpy(zSql, aData+iSql, nSql);
    zSql[nSql] = 0;
976
977
978
979
980
981
982


983
984
985
986
987
988
989
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996







+
+







    int nAlloc = 0;
    int nNotUsed = 0;
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
    fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n",
            sqlite3_memory_used(), nAlloc);
    exit(1);
  }
  sqlite3_hard_heap_limit64(0);
  sqlite3_soft_heap_limit64(0);
  return 0;
}

/*
** END of the dbsqlfuzz code
***************************************************************************/

1424
1425
1426
1427
1428
1429
1430
1431
1432
1433




1434
1435
1436
1437
1438
1439
1440
1431
1432
1433
1434
1435
1436
1437



1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448







-
-
-
+
+
+
+







"  --export-sql DIR     Write SQL to file(s) in DIR. Also works with --sqlid\n"
"  --help               Show this help text\n"
"  --info               Show information about SOURCE-DB w/o running tests\n"
"  --limit-depth N      Limit expression depth to N.  Default: 500\n"
"  --limit-heap N       Limit heap memory to N.  Default: 100M\n"
"  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
"  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
"  --load-sql ARGS...   Load SQL scripts fron files into SOURCE-DB\n"
"  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
"  --load-dbsql ARGS..  Load dbsqlfuzz outputs into the xsql table\n"
"  --load-sql   FILE..  Load SQL scripts fron files into SOURCE-DB\n"
"  --load-db    FILE..  Load template databases from files into SOURCE_DB\n"
"  --load-dbsql FILE..  Load dbsqlfuzz outputs into the xsql table\n"
"               ^^^^------ Use \"-\" for FILE to read filenames from stdin\n"
"  -m TEXT              Add a description to the database\n"
"  --native-vfs         Use the native VFS for initially empty database files\n"
"  --native-malloc      Turn off MEMSYS3/5 and Lookaside\n"
"  --oss-fuzz           Enable OSS-FUZZ testing\n"
"  --prng-seed N        Seed value for the PRGN inside of SQLite\n"
"  -q|--quiet           Reduced output\n"
"  --rebuild            Rebuild and vacuum the database file\n"
1767
1768
1769
1770
1771
1772
1773













1774
1775
1776
1777






1778
1779
1780
1781
1782
1783
1784
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







+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+







                              isDbSqlFunc, 0, 0);
      rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
      if( rc ) fatalError("cannot prepare statement [%s]: %s",
                          zInsSql, sqlite3_errmsg(db));
      rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
      if( rc ) fatalError("cannot start a transaction");
      for(i=iFirstInsArg; i<argc; i++){
        if( strcmp(argv[i],"-")==0 ){
          /* A filename of "-" means read multiple filenames from stdin */
          char zLine[2000];
          while( rc==0 && fgets(zLine,sizeof(zLine),stdin)!=0 ){
            size_t kk = strlen(zLine);
            while( kk>0 && zLine[kk-1]<=' ' ) kk--;
            sqlite3_bind_text(pStmt, 1, zLine, kk, SQLITE_STATIC);
            if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
            sqlite3_step(pStmt);
            rc = sqlite3_reset(pStmt);
            if( rc ) fatalError("insert failed for %s", zLine);
          }
        }else{
        sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc ) fatalError("insert failed for %s", argv[i]);
          sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
          if( verboseFlag ) printf("loading %s\n", argv[i]);
          sqlite3_step(pStmt);
          rc = sqlite3_reset(pStmt);
          if( rc ) fatalError("insert failed for %s", argv[i]);
        }
      }
      sqlite3_finalize(pStmt);
      rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
      if( rc ) fatalError("cannot commit the transaction: %s",
                          sqlite3_errmsg(db));
      rebuild_database(db, dbSqlOnly);
      sqlite3_close(db);
2039
2040
2041
2042
2043
2044
2045

2046

2047
2048
2049
2050
2051
2052
2053
2062
2063
2064
2065
2066
2067
2068
2069

2070
2071
2072
2073
2074
2075
2076
2077







+
-
+







            iSrcDb = nSrcDb-1;
            goto sourcedb_cleanup;
          }
        }
      }
    }
    if( bSpinner ){
      int nTotal = g.nDb*g.nSql;
      printf("\n");
      printf("\r%s: %d/%d   \n", zDbName, nTotal, nTotal);
    }else if( !quietFlag && !verboseFlag ){
      printf(" 100%% - %d tests\n", g.nDb*g.nSql);
    }
  
    /* Clean up at the end of processing a single source database
    */
  sourcedb_cleanup:
Changes to test/fuzzdata8.db.

cannot compute difference between binary files

Changes to test/hook.test.
1011
1012
1013
1014
1015
1016
1017
1018
1011
1012
1013
1014
1015
1016
1017








-
} {}

do_catchsql_test 12.6 {
  INSERT INTO t4 VALUES('def', 3);
} {1 {UNIQUE constraint failed: t4.a}}

finish_test

Changes to test/in4.test.
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340







-
+







  INSERT INTO t6b VALUES(4,44),(5,55),(6,66);

  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {3 4 4 44}
do_execsql_test in4-6.1-eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {~/SCAN TABLE t6a/}
} {~/SCAN t6a/}
do_execsql_test in4-6.2 {
  SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {3 4 4 44}
do_execsql_test in4-6.2-eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {~/SCAN/}
Changes to test/in6.test.
92
93
94
95
96
97
98



















99
100
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test in6-3.110 {
  CREATE TABLE v0(v1);
  CREATE TABLE v3(v5, v4);
  INSERT INTO v0 VALUES(0);
  CREATE INDEX v9 ON v3(v4, v4, v5);
  SELECT quote(v5) FROM v0 LEFT JOIN v3 ON v4 = NULL AND v5 IN(0);
} {NULL}

# 2021-04-29 forum https://sqlite.org/forum/forumpost/6a3ec138e9
# An early OP_IsNull bypass might skip over the OP_Affinity and
# cause the OP_IfNoHope to jump on a false-positive, resulting in
# incomplete output.
#
reset_db
do_execsql_test in6-3.120 {
  CREATE TABLE t1(a TEXT, b TEXT);
  INSERT INTO t1 VALUES(null,10),(0,10),(10,10);
  CREATE INDEX t1ab ON t1(a,b);
  SELECT quote(a), quote(b), '|' FROM t1 WHERE b in (SELECT a FROM t1) AND a=0;
} {'0' '10' |}
do_execsql_test in6-3.130 {
  CREATE TABLE t2(x TEXT);
  INSERT INTO t2(x) VALUES(NULL),(0),(10);
  SELECT quote(x), quote(a), quote(b), 'x'
    FROM t2 LEFT JOIN t1 ON a=x AND b in (null,0,10);
} {NULL NULL NULL x '0' '0' '10' x '10' '10' '10' x}

finish_test
Changes to test/incrvacuum.test.
828
829
830
831
832
833
834
835

























































836
828
829
830
831
832
833
834

835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
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







-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

    db eval { SELECT a FROM t3 } {
      if {$a==3} { db eval COMMIT }
      lappend res $a
    }
    set res
  } {1 2 3 4}
}
  

# 2021-04-05 dbsqlfuzz cced0668cfd4da4eb2382cb9dd26c17c64aaff76
#
# This is an incremental vacuum database that has one free page that
# needs to be filled.  After removing the last page from the end of
# the database file to fill the free page slot, the last page that
# is left is the tail of an overflow chain.
#
# But the size of the database file is shorter than the actual data
# so that after incremental vacuum runs, the file is actually too
# small to hold the last page of the overflow chain.
#
# At one point this caused an assertion fault in 
# sqlite3PagerTruncateImage().
#
do_test incrvacuum-17.0 {
  sqlite3 db {}
  database_may_be_corrupt
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename x2.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 05 00 00 00 07   .....@  ........
|     32: 00 00 00 04 00 00 00 01 00 00 00 03 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 03 00 00 00 01 00 00 00 00   ................
|     64: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
|     96: 00 2e 53 60 0d 0f dc 00 01 0f b8 00 0f b8 0f b8   ..S`............
|   4016: 00 00 00 00 00 00 00 00 22 02 06 17 11 11 01 31   ...............1
|   4032: 74 61 62 6c 65 74 32 74 32 03 43 52 45 41 54 45   tablet2t2.CREATE
|   4048: 20 54 41 42 4c 45 20 74 32 28 79 29 00 00 00 24    TABLE t2(y)...$
|   4064: 11 11 01 31 74 61 62 6c 65 74 31 74 31 03 43 52   ...1tablet1t1.CR
|   4080: 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 78 29   EATE TABLE t1(x)
| page 2 offset 4096
|      0: 01 00 00 00 00 02 00 00 00 00 03 00 00 00 03 04   ................
|     16: 00 00 00 05 03 00 00 00 03 00 00 00 00 00 00 00   ................
| page 3 offset 8192
|      0: 0d 00 00 00 02 05 47 00 08 dd 05 47 00 00 00 00   ......G....G....
|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................
|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................
|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
| page 4 offset 12288
|      0: 00 00 00 00 00 00 00 00 08 dd 05 47 00 00 00 00   ...........G....
|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................
|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................
|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
| page 5 offset 16384
|      0: 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00   ................
| end x2.db
}]} {}
do_catchsql_test incrvacuum-17.1 {
  PRAGMA writable_schema=ON;
  PRAGMA incremental_vacuum(10);
} {0 {}}

finish_test
Changes to test/index6.test.
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
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







-
+







-
+






-
+






-
+







  }
} {500}
do_test index6-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/.* TABLE t2 USING INDEX t2a1 .*/}
} {/(SEARCH|SCAN) t2 USING INDEX t2a1 /}
ifcapable stat4 {
  execsql ANALYZE
  do_test index6-2.3stat4 {
    execsql {
      EXPLAIN QUERY PLAN
      SELECT * FROM t2 WHERE a IS NOT NULL;
    }
  } {/.* TABLE t2 USING INDEX t2a1 .*/}
  } {/(SEARCH|SCAN) t2 USING INDEX t2a1 /}
} else {
  do_test index6-2.3stat4 {
    execsql {
      EXPLAIN QUERY PLAN
      SELECT * FROM t2 WHERE a IS NOT NULL AND a>0;
    }
  } {/.* TABLE t2 USING INDEX t2a1 .*/}
  } {/(SEARCH|SCANE) t2 USING INDEX t2a1 /}
}
do_test index6-2.4 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a IS NULL;
  }
} {~/.*INDEX t2a1.*/}
} {~/INDEX t2a1/}

do_execsql_test index6-2.101 {
  DROP INDEX t2a1;
  UPDATE t2 SET a=b, b=b+10000;
  SELECT b FROM t2 WHERE a=15;
} {10015}
do_execsql_test index6-2.102 {
315
316
317
318
319
320
321
322
323


324
325
326
327
328
329
330
315
316
317
318
319
320
321


322
323
324
325
326
327
328
329
330







-
-
+
+







  INSERT INTO t8b VALUES('dummy', 4);
} {}

do_eqp_test index6-8.1 {
  SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
  QUERY PLAN
  |--SCAN TABLE t8a
  `--SEARCH TABLE t8b USING INDEX i8c (y=?)
  |--SCAN t8a
  `--SEARCH t8b USING INDEX i8c (y=?)
}

do_execsql_test index6-8.2 {
  SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
  1 one value 1 
  2 two {} {} 
Changes to test/index7.test.
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123







-
+







  INSERT INTO t1(a,b,c)
     VALUES('abcde',1,101),('abdef',2,102),('xyz',3,103),('abcz',4,104);
  SELECT c FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
} {7}
do_execsql_test index7-1.7eqp {
  EXPLAIN QUERY PLAN
  SELECT b FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
} {/SEARCH TABLE t1 USING COVERING INDEX bad1 /}
} {/SEARCH t1 USING COVERING INDEX bad1 /}
do_execsql_test index7-1.8 {
  DELETE FROM t1 WHERE c>=101;
  DROP INDEX IF EXISTS bad1;
} {}

do_test index7-1.10 {
  execsql {
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212

213
214
215
216
217
218
219

220
221
222
223
224
225
226

227
228
229
230
231
232
233
198
199
200
201
202
203
204

205
206
207
208
209
210
211

212
213
214
215
216
217
218

219
220
221
222
223
224
225

226
227
228
229
230
231
232
233







-
+






-
+






-
+






-
+







  }
} {800}
do_test index7-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
} {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
ifcapable stat4 {
  do_test index7-2.3stat4 {
    execsql {
      EXPLAIN QUERY PLAN
      SELECT * FROM t2 WHERE a IS NOT NULL;
    }
  } {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
  } {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
} else {
  do_test index7-2.3stat4 {
    execsql {
      EXPLAIN QUERY PLAN
      SELECT * FROM t2 WHERE a IS NOT NULL AND a>0;
    }
  } {/.* TABLE t2 USING COVERING INDEX t2a1 .*/}
  } {/(SCAN|SEARCH) t2 USING COVERING INDEX t2a1 /}
}
do_test index7-2.4 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a IS NULL;
  }
} {~/.*INDEX t2a1.*/}
} {~/INDEX t2a1/}

do_execsql_test index7-2.101 {
  DROP INDEX t2a1;
  UPDATE t2 SET a=b, b=b+10000;
  SELECT b FROM t2 WHERE a=15;
} {10015}
do_execsql_test index7-2.102 {
317
318
319
320
321
322
323
324

325
326
327
328
329
330
331
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331







-
+







  INSERT INTO t4 VALUES('def', 'xyz');
  SELECT * FROM v4 WHERE d='xyz' AND c='def'
} {
  def xyz
}
do_eqp_test index7-6.4 {
  SELECT * FROM v4 WHERE d='xyz' AND c='def'
} {SEARCH TABLE t4 USING INDEX i4 (c=?)}
} {SEARCH t4 USING INDEX i4 (c=?)}

do_catchsql_test index7-6.5 {
  CREATE INDEX t5a ON t5(a) WHERE a=#1;
} {1 {near "#1": syntax error}}

do_execsql_test index7-7.0 {
  CREATE TABLE t6(x, y);
345
346
347
348
349
350
351
352

353
354
355
345
346
347
348
349
350
351

352
353
354
355







-
+



reset_db
do_execsql_test index7-8.1 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  CREATE INDEX t1y ON t1(y) WHERE y IS NOT NULL;
  INSERT INTO t1(x) VALUES(1),(2);
  ANALYZE;
  EXPLAIN QUERY PLAN SELECT 1 FROM t1 WHERE y=5;
} {/SEARCH TABLE t1 USING COVERING INDEX t1y/}
} {/SEARCH t1 USING COVERING INDEX t1y/}


finish_test
Changes to test/index8.test.
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
+








# Prior to the fix, the following EQP would show a table scan and a sort
# rather than an index scan.
#
do_execsql_test 1.0eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {/SCAN TABLE t1 USING INDEX t1abc/}
} {/SCAN t1 USING INDEX t1abc/}

# If we change the index so that it no longer covers the WHERE clause,
# then we should (correctly) revert to using a table scan.
#
do_execsql_test 1.1 {
  DROP INDEX t1abc;
  CREATE INDEX t1abd ON t1(a,b,d);
Changes to test/indexedby.test.
38
39
40
41
42
43
44
45

46
47
48

49
50
51
52
53
54


55
56
57
58
59
60
61
38
39
40
41
42
43
44

45
46
47

48
49
50
51
52


53
54
55
56
57
58
59
60
61







-
+


-
+




-
-
+
+







  uplevel "execsql {EXPLAIN QUERY PLAN $sql}"
}

# These tests are to check that "EXPLAIN QUERY PLAN" is working as expected.
#
do_eqp_test indexedby-1.2 {
  select * from t1 WHERE a = 10; 
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-1.3 {
  select * from t1 ; 
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test indexedby-1.4 {
  select * from t1, t2 WHERE c = 10; 
} {
  QUERY PLAN
  |--SEARCH TABLE t2 USING INDEX i3 (c=?)
  `--SCAN TABLE t1
  |--SEARCH t2 USING INDEX i3 (c=?)
  `--SCAN t1
}

# Parser tests. Test that an INDEXED BY or NOT INDEX clause can be 
# attached to a table in the FROM clause, but not to a sub-select or
# SQL view. Also test that specifying an index that does not exist or
# is attached to a different table is detected as an error.
#
114
115
116
117
118
119
120
121

122
123
124

125
126
127

128
129
130
131
132

133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223

224
225
226
227
228
229
230
231
232
233

234
235
236

237
238
239

240
241
242

243
244
245

246
247
248
249
250
251
252
253
254

255
256
257

258
259
260

261
262
263

264
265
266

267
268
269
270
271
272
273
114
115
116
117
118
119
120

121
122
123

124
125
126

127
128
129
130
131

132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167


168
169
170
171
172
173
174


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222

223
224
225
226
227
228
229
230
231
232

233
234
235

236
237
238

239
240
241

242
243
244

245
246
247
248
249
250
251
252
253

254
255
256

257
258
259

260
261
262

263
264
265

266
267
268
269
270
271
272
273







-
+


-
+


-
+




-
+


-
+















-
+


-
+













-
-
+
+





-
-
+
+



















-
+


-
+




















-
+


-
+









-
+


-
+


-
+


-
+


-
+








-
+


-
+


-
+


-
+


-
+







# index shall be used when accessing the preceding table, including
# implied indices create by UNIQUE and PRIMARY KEY constraints. However,
# the rowid can still be used to look up entries even when "NOT INDEXED"
# is specified.
#
do_eqp_test indexedby-3.1 {
  SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
} {/SEARCH TABLE t1 USING INDEX/}
} {/SEARCH t1 USING INDEX/}
do_eqp_test indexedby-3.1.1 {
  SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test indexedby-3.1.2 {
  SELECT * FROM t1 NOT INDEXED WHERE rowid=1
} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/}
} {/SEARCH t1 USING INTEGER PRIMARY KEY .rowid=/}


do_eqp_test indexedby-3.2 {
  SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-3.3 {
  SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-3.4 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.5 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
} {0 {}}
do_test indexedby-3.6 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.7 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
} {0 {}}

do_eqp_test indexedby-3.8 {
  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e 
} {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}
} {SCAN t3 USING INDEX sqlite_autoindex_t3_1}
do_eqp_test indexedby-3.9 {
  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE e = 10 
} {SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
} {SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
do_test indexedby-3.10 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
} {0 {}}
do_test indexedby-3.11 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 }
} {1 {no such index: sqlite_autoindex_t3_2}}

# Tests for multiple table cases.
#
do_eqp_test indexedby-4.1 {
  SELECT * FROM t1, t2 WHERE a = c 
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SEARCH TABLE t2 USING INDEX i3 (c=?)
  |--SCAN t1
  `--SEARCH t2 USING INDEX i3 (c=?)
}
do_eqp_test indexedby-4.2 {
  SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c 
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING INDEX i1
  `--SEARCH TABLE t2 USING INDEX i3 (c=?)
  |--SCAN t1 USING INDEX i1
  `--SEARCH t2 USING INDEX i3 (c=?)
}
do_test indexedby-4.3 {
  catchsql {
    SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
  }
} {0 {}}
do_test indexedby-4.4 {
  catchsql {
    SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
  }
} {0 {}}

# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
# also tests that nothing bad happens if an index refered to by
# a CREATE VIEW statement is dropped and recreated.
#
do_execsql_test indexedby-5.1 {
  CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
  EXPLAIN QUERY PLAN SELECT * FROM v2 
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_execsql_test indexedby-5.2 {
  EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_test indexedby-5.3 {
  execsql { DROP INDEX i1 }
  catchsql { SELECT * FROM v2 }
} {1 {no such index: i1}}
do_test indexedby-5.4 {
  # Recreate index i1 in such a way as it cannot be used by the view query.
  execsql { CREATE INDEX i1 ON t1(b) }
  catchsql { SELECT * FROM v2 }
} {0 {}}
do_test indexedby-5.5 {
  # Drop and recreate index i1 again. This time, create it so that it can
  # be used by the query.
  execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) }
  catchsql { SELECT * FROM v2 }
} {0 {}}

# Test that "NOT INDEXED" may use the rowid index, but not others.
# 
do_eqp_test indexedby-6.1 {
  SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
} {SEARCH t1 USING INDEX i2 (b=?)}
do_eqp_test indexedby-6.2 {
  SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
} {SCAN TABLE t1}
} {SCAN t1}

# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite
# query planner to use a particular named index on a DELETE, SELECT, or
# UPDATE statement.
#
# Test that "INDEXED BY" can be used in a DELETE statement.
# 
do_eqp_test indexedby-7.1 {
  DELETE FROM t1 WHERE a = 5 
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.2 {
  DELETE FROM t1 NOT INDEXED WHERE a = 5 
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test indexedby-7.3 {
  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.4 {
  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.5 {
  DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-7.6 {
  catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
} {0 {}}

# Test that "INDEXED BY" can be used in an UPDATE statement.
# 
do_eqp_test indexedby-8.1 {
  UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
} {SEARCH t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.2 {
  UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test indexedby-8.3 {
  UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 
} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
} {SEARCH t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.4 {
  UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
} {SEARCH t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-8.5 {
  UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-8.6 {
  catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
} {0 {}}

# Test that bug #3560 is fixed.
#
do_test indexedby-9.1 {
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
334
335
336
337
338
339
340

341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
369







-
+




















-
+







  SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3';
} {1 1 3}
do_execsql_test 11.4 {
  SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
} {1 1 3}
do_eqp_test 11.5 {
  SELECT a,b,rowid FROM x1 INDEXED BY x1i WHERE a=1 AND b=1 AND rowid='3.0';
} {SEARCH TABLE x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}
} {SEARCH x1 USING COVERING INDEX x1i (a=? AND b=? AND rowid=?)}

do_execsql_test 11.6 {
  CREATE TABLE x2(c INTEGER PRIMARY KEY, a, b TEXT);
  CREATE INDEX x2i ON x2(a, b);
  INSERT INTO x2 VALUES(1, 1, 1);
  INSERT INTO x2 VALUES(2, 1, 1);
  INSERT INTO x2 VALUES(3, 1, 1);
  INSERT INTO x2 VALUES(4, 1, 1);
}
do_execsql_test 11.7 {
  SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c=3;
} {1 1 3}
do_execsql_test 11.8 {
  SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3';
} {1 1 3}
do_execsql_test 11.9 {
  SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
} {1 1 3}
do_eqp_test 11.10 {
  SELECT a,b,c FROM x2 INDEXED BY x2i WHERE a=1 AND b=1 AND c='3.0';
} {SEARCH TABLE x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}
} {SEARCH x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}

#-------------------------------------------------------------------------
# Check INDEXED BY works (throws an exception) with partial indexes that 
# cannot be used.
do_execsql_test 12.1 {
  CREATE TABLE o1(x INTEGER PRIMARY KEY, y, z);
  CREATE INDEX p1 ON o1(z);
Changes to test/indexexpr1.test.
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107

108
109
110
111
112
113
114
93
94
95
96
97
98
99

100
101
102
103
104
105
106

107
108
109
110
111
112
113
114







-
+






-
+







do_execsql_test indexexpr1-170 {
  CREATE INDEX t1alen ON t1(length(a));
  SELECT length(a) FROM t1 ORDER BY length(a);
} {20 25 27 29 38 52}
do_execsql_test indexexpr1-170eqp {
  EXPLAIN QUERY PLAN
  SELECT length(a) FROM t1 ORDER BY length(a);
} {/SCAN TABLE t1 USING INDEX t1alen/}
} {/SCAN t1 USING INDEX t1alen/}
do_execsql_test indexexpr1-171 {
  SELECT length(a) FROM t1 ORDER BY length(a) DESC;
} {52 38 29 27 25 20}
do_execsql_test indexexpr1-171eqp {
  EXPLAIN QUERY PLAN
  SELECT length(a) FROM t1 ORDER BY length(a) DESC;
} {/SCAN TABLE t1 USING INDEX t1alen/}
} {/SCAN t1 USING INDEX t1alen/}

do_execsql_test indexexpr1-200 {
  DROP TABLE t1;
  CREATE TABLE t1(id ANY PRIMARY KEY, a,b,c) WITHOUT ROWID;
  INSERT INTO t1(id,a,b,c)
  VALUES(1,'In_the_beginning_was_the_Word',1,1),
        (2,'and_the_Word_was_with_God',1,2),
Changes to test/indexexpr2.test.
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
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







-
+














-
+







  do_eqp_test 3.3.1 {
    SELECT json_extract(x, '$.b') FROM t2 
    WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL 
    GROUP BY json_extract(x, '$.b') COLLATE nocase
    ORDER BY json_extract(x, '$.b') COLLATE nocase;
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--SCAN TABLE t2
    |--SCAN t2
    `--USE TEMP B-TREE FOR GROUP BY
  }]
  
  do_execsql_test 3.3.2 {
    CREATE INDEX i3 ON t3(json_extract(x, '$.a'), json_extract(x, '$.b'));
  } {}
  
  do_eqp_test 3.3.3 {
    SELECT json_extract(x, '$.b') FROM t3 
    WHERE json_extract(x, '$.b') IS NOT NULL AND json_extract(x, '$.a') IS NULL 
    GROUP BY json_extract(x, '$.b') COLLATE nocase
    ORDER BY json_extract(x, '$.b') COLLATE nocase;
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--SEARCH TABLE t3 USING INDEX i3 (<expr>=?)
    |--SEARCH t3 USING INDEX i3 (<expr>=?)
    `--USE TEMP B-TREE FOR GROUP BY
  }]
}

do_execsql_test 3.4.0 {
  CREATE TABLE t4(a, b);
  INSERT INTO t4 VALUES('.ABC', 1);
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164







-
+







do_execsql_test 3.4.5 {
  CREATE INDEX i4 ON t4( Substr(a,-2) COLLATE nocase );
  SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE nocase;
} {.ABC1 1 .abc2 2 .ABC3 3 .abc4 4}
do_execsql_test 3.4.5eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE nocase;
} {/SCAN TABLE t4 USING INDEX i4/}
} {/SCAN t4 USING INDEX i4/}
do_execsql_test 3.4.6 {
  SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary;
} {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4}

# 2014-09-15:  Verify that UPDATEs of columns not referenced by a
# index on expression do not modify the index.
#
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286







-
+










-
+







} {1 123   2 123   3 123abc  4 123.0}
do_execsql_test 6.1.2 {
  CREATE INDEX x1i ON x1( CAST(b AS INTEGER) );
  SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
} {1 123   2 123   3 123abc  4 123.0}
do_eqp_test 6.1.3 {
  SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
} {SEARCH TABLE x1 USING INDEX x1i (<expr>=?)}
} {SEARCH x1 USING INDEX x1i (<expr>=?)}

do_execsql_test 6.2.1 {
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {1 123   2 123}
do_execsql_test 6.2.2 {
  CREATE INDEX x1i2 ON x1( CAST(b AS TEXT) );
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {1 123   2 123}
do_eqp_test 6.2.3 {
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {SEARCH TABLE x1 USING INDEX x1i2 (<expr>=?)}
} {SEARCH x1 USING INDEX x1i2 (<expr>=?)}

do_execsql_test 7.0 {
  CREATE TABLE IF NOT EXISTS t0(c0);
  INSERT INTO t0(c0) VALUES (-9223372036854775808);
  BEGIN;
}
do_catchsql_test 7.1 {
Changes to test/intpkey.test.
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139







-
+







  }
} {4 one two}
do_test intpkey-1.12.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t1 WHERE a==4;
  }
} {/SEARCH TABLE t1 /}
} {/SEARCH t1 /}

# Try to insert a non-integer value into the primary key field.  This
# should result in a data type mismatch.
#
do_test intpkey-1.13.1 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES('x','y','z');
Changes to test/join2.test.
109
110
111
112
113
114
115
116
117


118
119
120
121
122
123
124
125


126
127
128
129
130
131
132
109
110
111
112
113
114
115


116
117
118
119
120
121
122
123


124
125
126
127
128
129
130
131
132







-
-
+
+






-
-
+
+







  CREATE TABLE t3_2(v3, k3 PRIMARY KEY) WITHOUT ROWID;
}

do_eqp_test 3.1 {
  SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_eqp_test 3.2 {
  SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t1
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

#-------------------------------------------------------------------------
# Test that tables other than the rightmost can be omitted from a
# LEFT JOIN query.
#
do_execsql_test 4.0 {
157
158
159
160
161
162
163
164
165
166



167
168
169
170
171
172
173


174
175
176
177
178
179
180
157
158
159
160
161
162
163



164
165
166
167
168
169
170
171


172
173
174
175
176
177
178
179
180







-
-
-
+
+
+





-
-
+
+







  SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
} {2 v3 2 v3 1112 {} 1112 {}}

do_eqp_test 4.1.5 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
  QUERY PLAN
  |--SCAN TABLE c1
  |--SEARCH TABLE c2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN c1
  |--SEARCH c2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test 4.1.6 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
  QUERY PLAN
  |--SCAN TABLE c1
  `--SEARCH TABLE c3 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN c1
  `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}

do_execsql_test 4.2.0 {
  DROP TABLE c1;
  DROP TABLE c2;
  DROP TABLE c3;
  CREATE TABLE c1(k UNIQUE, v1);
204
205
206
207
208
209
210
211
212
213



214
215
216
217
218
219
220


221
222
223
224
225
226
227
204
205
206
207
208
209
210



211
212
213
214
215
216
217
218


219
220
221
222
223
224
225
226
227







-
-
-
+
+
+





-
-
+
+







  SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
} {2 v3 2 v3 1112 {} 1112 {}}

do_eqp_test 4.2.5 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
  QUERY PLAN
  |--SCAN TABLE c1
  |--SEARCH TABLE c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
  `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
  |--SCAN c1
  |--SEARCH c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
  `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}
do_eqp_test 4.2.6 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
  QUERY PLAN
  |--SCAN TABLE c1
  `--SEARCH TABLE c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
  |--SCAN c1
  `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}

# 2017-11-23 (Thanksgiving day)
# OSSFuzz found an assertion fault in the new LEFT JOIN eliminator code.
#
do_execsql_test 4.3.0 {
  DROP TABLE IF EXISTS t1;
247
248
249
250
251
252
253
254

255
256
257
258

259
260
261
262
263
264
265
266
267

268
269
270
271
272
273
274
247
248
249
250
251
252
253

254
255
256
257

258
259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274







-
+



-
+








-
+







  CREATE TABLE s1 (a INTEGER PRIMARY KEY);
  CREATE TABLE s2 (a INTEGER PRIMARY KEY);
  CREATE TABLE s3 (a INTEGER);
  CREATE UNIQUE INDEX ndx on s3(a);
}
do_eqp_test 5.1 {
  SELECT s1.a FROM s1 left join s2 using (a);
} {SCAN TABLE s1}
} {SCAN s1}

do_eqp_test 5.2 {
  SELECT s1.a FROM s1 left join s3 using (a);
} {SCAN TABLE s1}
} {SCAN s1}

do_execsql_test 6.0 {
  CREATE TABLE u1(a INTEGER PRIMARY KEY, b, c);
  CREATE TABLE u2(a INTEGER PRIMARY KEY, b, c);
  CREATE INDEX u1ab ON u1(b, c);
}
do_eqp_test 6.1 {
  SELECT u2.* FROM u2 LEFT JOIN u1 ON( u1.a=u2.a AND u1.b=u2.b AND u1.c=u2.c );
} {SCAN TABLE u2}
} {SCAN u2}

db close
sqlite3 db :memory:
do_execsql_test 7.0 {
  CREATE TABLE t1(a,b);  INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
  CREATE TABLE t2(c,d);  INSERT INTO t2 VALUES(2,4),(3,6);
  CREATE TABLE t3(x);    INSERT INTO t3 VALUES(9);
Changes to test/join5.test.
273
274
275
276
277
278
279
280

281
282
283

284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306


307
308
309
310
311
312
313
273
274
275
276
277
278
279

280
281
282

283
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313







-
+


-
+

-
+



















-
-
+
+








do_eqp_test 7.2 {
  SELECT * FROM t1 LEFT JOIN t2 ON (
    t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL))
  );
} {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN t1
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
     |  `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
     `--INDEX 2
        `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
        `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
}

do_execsql_test 7.3 {
  CREATE TABLE t3(x);

  CREATE TABLE t4(x, y, z);
  CREATE INDEX t4xy ON t4(x, y);
  CREATE INDEX t4xz ON t4(x, z);

  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
  INSERT INTO t4 SELECT i/10, i, i FROM s;

  ANALYZE;
}

do_eqp_test 7.4 {
  SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
} {
  QUERY PLAN
  |--SCAN TABLE t3
  `--SEARCH TABLE t4 USING INDEX t4xz (x=?)
  |--SCAN t3
  `--SEARCH t4 USING INDEX t4xz (x=?)
} 

reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0 (c0, c1, PRIMARY KEY (c0, c1));
  CREATE TABLE t1 (c0);

Changes to test/like.test.
164
165
166
167
168
169
170
171
172


173
174
175


176
177

178
179
180
181
182
183
184
164
165
166
167
168
169
170


171
172
173


174
175
176

177
178
179
180
181
182
183
184







-
-
+
+

-
-
+
+

-
+







  db cache flush
  set data [execsql $sql]
  if {$::sqlite_sort_count} {set x sort} {set x nosort}
  lappend data $x
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  # puts eqp=$eqp
  foreach {a b c x} $eqp {
    if {[regexp { TABLE (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
        $x all as tab idx]} {
    if {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data {} $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

# Perform tests on the like optimization.
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736







-
+







    }]
  } {0 {x hello}}
  ifcapable explain {
    do_test like-9.4.3 {
      set res [sqlite3_exec_hex db {
         EXPLAIN QUERY PLAN SELECT x FROM t2 WHERE x LIKE '%ff%25'
      }]
      regexp {SCAN TABLE t2} $res
      regexp {SCAN t2} $res
    } {1}
  }
  do_test like-9.5.1 {
    set res [sqlite3_exec_hex db {
       SELECT x FROM t2 WHERE x LIKE '%fe%25'
    }]
  } {0 {}}
1032
1033
1034
1035
1036
1037
1038

1039
1040


1041
1042
1043
1044
1045
1046

1047
1048


1049
1050
1051
1052
1053
1054
1055
1032
1033
1034
1035
1036
1037
1038
1039


1040
1041
1042
1043
1044
1045
1046
1047
1048


1049
1050
1051
1052
1053
1054
1055
1056
1057







+
-
-
+
+






+
-
-
+
+







# Performance testing for patterns with many wildcards.  These LIKE and GLOB
# patterns were quite slow with SQLite 3.15.2 and earlier.
#
do_test like-14.1 {
  set x [lindex [time {
    db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'GLOB'*a*a*a*a*a*a*a*a*y'}
  }] 0]
  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
  puts -nonewline " ($x ms - want less than 1000) "
  expr {$x<1000}
  puts -nonewline " ($x ms - want less than $tlimit) "
  expr {$x<$tlimit}
} {1}
ifcapable !icu {
  do_test like-14.2 {
    set x [lindex [time {
      db one {SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz'LIKE'%a%a%a%a%a%a%a%a%y'}
    }] 0]
  set tlimit [expr {1000 * $::sqlite_options(configslower)}]
    puts -nonewline " ($x ms - want less than 1000) "
    expr {$x<1000}
  puts -nonewline " ($x ms - want less than $tlimit) "
  expr {$x<$tlimit}
  } {1}
}

ifcapable !icu {
# As of 2017-07-27 (3.21.0) the LIKE optimization works with ESCAPE as
# long as the ESCAPE is a single-byte literal.
#
Changes to test/like3.test.
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
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







-
+









-
+









-
+








-
+











-
+








-
+







  INSERT INTO t5a(x) VALUES('/abc'),(123),(-234);
  SELECT x FROM t5a WHERE x LIKE '/%';
} {/abc}
do_eqp_test like3-5.101 {
  SELECT x FROM t5a WHERE x LIKE '/%';
} {
  QUERY PLAN
  `--SCAN TABLE t5a
  `--SCAN t5a
}
do_execsql_test like3-5.110 {
  SELECT x FROM t5a WHERE x LIKE '/a%';
} {/abc}
ifcapable !icu {
do_eqp_test like3-5.111 {
  SELECT x FROM t5a WHERE x LIKE '/a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x<?)
  `--SEARCH t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x<?)
}
}
do_execsql_test like3-5.120 {
  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {123}
do_eqp_test like3-5.121 {
  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {
  QUERY PLAN
  `--SCAN TABLE t5a
  `--SCAN t5a
}
do_execsql_test like3-5.122 {
  SELECT x FROM t5a WHERE x LIKE '^-2%' ESCAPE '^';
} {-234}
do_eqp_test like3-5.123 {
  SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^';
} {
  QUERY PLAN
  `--SCAN TABLE t5a
  `--SCAN t5a
}

do_execsql_test like3-5.200 {
  CREATE TABLE t5b(x INT UNIQUE COLLATE binary);
  INSERT INTO t5b(x) VALUES('/abc'),(123),(-234);
  SELECT x FROM t5b WHERE x GLOB '/*';
} {/abc}
do_eqp_test like3-5.201 {
  SELECT x FROM t5b WHERE x GLOB '/*';
} {
  QUERY PLAN
  `--SCAN TABLE t5b
  `--SCAN t5b
}
do_execsql_test like3-5.210 {
  SELECT x FROM t5b WHERE x GLOB '/a*';
} {/abc}
do_eqp_test like3-5.211 {
  SELECT x FROM t5b WHERE x GLOB '/a*';
} {
  QUERY PLAN
  `--SEARCH TABLE t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x<?)
  `--SEARCH t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x<?)
}

# 2019-05-01
# another case of the above reported on the mailing list by Manuel Rigger.
#
do_execsql_test like3-5.300 {
  CREATE TABLE t5c (c0 REAL);
230
231
232
233
234
235
236
237

238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261

262
263
264
265
266
267
268

269
270
271
272
273
274

275
276
277
278
230
231
232
233
234
235
236

237
238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260

261
262
263
264
265
266
267

268
269
270
271
272
273

274
275
276
277
278







-
+





-
+











-
+





-
+






-
+





-
+




  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(path TEXT COLLATE nocase PRIMARY KEY,a,b,c) WITHOUT ROWID;
}
do_eqp_test like3-6.110 {
  SELECT * FROM t1 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
  `--SEARCH t1 USING PRIMARY KEY (path>? AND path<?)
}
do_eqp_test like3-6.120 {
  SELECT * FROM t1 WHERE path LIKE 'a%' ESCAPE 'x';
} {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
  `--SEARCH t1 USING PRIMARY KEY (path>? AND path<?)
}
do_execsql_test like3-6.200 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(path TEXT,x,y,z);
  CREATE INDEX t2path ON t2(path COLLATE nocase);
  CREATE INDEX t2path2 ON t2(path);
}
do_eqp_test like3-6.210 {
  SELECT * FROM t2 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
  `--SEARCH t2 USING INDEX t2path (path>? AND path<?)
}
do_eqp_test like3-6.220 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
  `--SEARCH t2 USING INDEX t2path (path>? AND path<?)
}
db eval {PRAGMA case_sensitive_like=ON}
do_eqp_test like3-6.230 {
  SELECT * FROM t2 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
  `--SEARCH t2 USING INDEX t2path2 (path>? AND path<?)
}
do_eqp_test like3-6.240 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
  `--SEARCH t2 USING INDEX t2path2 (path>? AND path<?)
}
}

finish_test
Changes to test/mallocK.test.
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133







-
+







} {1}

ifcapable stat4 {
  do_eqp_test 6.1 {
    SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx';
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--SEARCH TABLE t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)
    |--SEARCH t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)
    `--USE TEMP B-TREE FOR DISTINCT
  }]
}

do_faultsim_test 6 -faults oom* -body {
  db cache flush
  db eval { SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx' }
Changes to test/memdb1.test.
153
154
155
156
157
158
159










160
161
162
163
164
165
166
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176







+
+
+
+
+
+
+
+
+
+







} {ok}
do_execsql_test 410 {
  CREATE TABLE t4(a,b);
  INSERT INTO t4 VALUES('hello','world!');
  PRAGMA integrity_check;
  SELECT * FROM t4;
} {ok hello world!}
do_execsql_test 420 {
  PRAGMA journal_mode=TRUNCATE;
  PRAGMA journal_mode=OFF;
  PRAGMA journal_mode=DELETE;
  PRAGMA journal_mode=WAL;
  PRAGMA journal_mode=PERSIST;
  PRAGMA journal_mode=MEMORY;
  PRAGMA journal_mode=OFF;
  PRAGMA journal_mode=DELETE;
} {truncate off delete delete persist memory off delete}

# Deserialize something that is not a database.
#
db close
sqlite3 db
do_test 500 {
  set rc [catch {db deserialize not-a-database} msg]
Changes to test/minmax.test.
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
290
291
292
293
294
295
296
297
298
299
300
301
302
303


304
305
306
307

308
309
310


311
312
313
314
315
316
317
318
319







+
+
+
+
+


-
-
+
+


-
+


-
-
+
+







  }
} {34 1234}

# Ticket #658:  Test the min()/max() optimization when the FROM clause
# is a subquery.
#
ifcapable {compound && subquery} {
  do_test minmax-9.0 {
    execsql {
      SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
    }
  } {3}
  do_test minmax-9.1 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {{}}
  } {3}
  do_test minmax-9.2 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
      )
    }
  } {{}}
} ;# ifcapable compound&&subquery

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
Changes to test/minmax2.test.
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
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







+
+
+
+
+


-
-
+
+


-
+


-
-
+
+







  }
} {34 1234}

# Ticket #658:  Test the min()/max() optimization when the FROM clause
# is a subquery.
#
ifcapable {compound && subquery} {
  do_test minmax2-9.0 {
    execsql {
      SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
    }
  } {3}
  do_test minmax2-9.1 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {{}}
  } {3}
  do_test minmax2-9.2 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
      )
    }
  } {{}}
} ;# ifcapable compound&&subquery

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
Changes to test/misc2.test.
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
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







-
+
-
-
-
+
+
+
+
+
+
-
-
+

-
+
-
-
-
+
+
-
-
+
+
+
+







    CREATE TABLE t1(a,b,c);
    INSERT INTO t1 VALUES(1,2,3);
    CREATE TABLE t2(a,b,c);
    INSERT INTO t2 VALUES(7,8,9);
  }
} {}
ifcapable subquery {
  do_test misc2-2.2 {
  do_catchsql_test misc2-2.2 {
    execsql {
      SELECT rowid, * FROM (SELECT * FROM t1, t2);
    }
    SELECT rowid, * FROM (SELECT * FROM t1, t2);
  } {1 {no such column: rowid}}
  do_catchsql_test misc2-2.2b {
    SELECT 'rowid', * FROM (SELECT * FROM t1, t2);
  } {0 {rowid 1 2 3 7 8 9}}
}
  } {{} 1 2 3 7 8 9}
}

ifcapable view {
  do_test misc2-2.3 {
  do_catchsql_test misc2-2.3 {
    execsql {
      CREATE VIEW v1 AS SELECT * FROM t1, t2;
      SELECT rowid, * FROM v1;
    CREATE VIEW v1 AS SELECT * FROM t1, t2;
    SELECT rowid, * FROM v1;
    }
  } {{} 1 2 3 7 8 9}
  } {1 {no such column: rowid}}
  do_catchsql_test misc2-2.3b {
    SELECT 'rowid', * FROM v1;
  } {0 {rowid 1 2 3 7 8 9}}
} ;# ifcapable view

# Ticket #2002 and #1952.
ifcapable subquery {
  do_test misc2-2.4 {
    execsql2 {
      SELECT * FROM (SELECT a, b AS 'a', c AS 'a', 4 AS 'a' FROM t1)
Changes to test/misc7.test.
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
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







-
+





-
+





-
+







  do_execsql_test misc7-14.0 {
    CREATE TABLE abc(a PRIMARY KEY, b, c);
  }
  do_eqp_test misc7-14.1 {
    SELECT * FROM abc AS t2 WHERE rowid = 1;
  } {
  QUERY PLAN
  `--SEARCH TABLE abc AS t2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}
  do_eqp_test misc7-14.2 {
    SELECT * FROM abc AS t2 WHERE a = 1;
} {
  QUERY PLAN
  `--SEARCH TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
  `--SEARCH t2 USING INDEX sqlite_autoindex_abc_1 (a=?)
}
  do_eqp_test misc7-14.3 {
    SELECT * FROM abc AS t2 ORDER BY a;
  } {
  QUERY PLAN
  `--SCAN TABLE abc AS t2 USING INDEX sqlite_autoindex_abc_1
  `--SCAN t2 USING INDEX sqlite_autoindex_abc_1
}
}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db
Changes to test/misc8.test.
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
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







-
+









-
+







  0 8 {} 10 {} {}
  0 9 {} 10 {} {} 
  0 10 {} 10 {} {}
}

# 2016-02-26: An assertion fault found by the libFuzzer project
#
do_execsql_test misc8-3.0 {
do_catchsql_test misc8-3.0 {
  SELECT *
    FROM
         (
           (SELECT 0 AS i) AS x1,
           (SELECT 1) AS x2
         ) AS x3,
         (SELECT 6 AS j UNION ALL SELECT 7) AS x4
   WHERE i<rowid
   ORDER BY 1;
} {0 1 6 0 1 7}
} {1 {no such column: rowid}}

# The SQLITE_DBCONFIG_MAINDBNAME interface
#
db close
forcedelete test.db test2.db
sqlite3 db test.db
do_execsql_test misc8-4.0 {
Changes to test/notnull2.test.
93
94
95
96
97
98
99
100

101











93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112







-
+

+
+
+
+
+
+
+
+
+
+
+
  CREATE TABLE T3(k, v);
}

do_execsql_test 2.1 {
  SELECT * FROM (SELECT a, b FROM t1) LEFT JOIN t3 ON a IS NULL;
}

finish_test


#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t0(c0 PRIMARY KEY);
  INSERT INTO t0(c0) VALUES (0);
}
do_execsql_test 3.1 {
  SELECT * FROM t0 WHERE ((c0 NOT NULL) AND 1) OR (c0 == NULL);
} {0}

finish_test
Changes to test/notnullfault.test.
49
50
51
52
53
54
55
56
49
50
51
52
53
54
55








-
    WINDOW win AS (ORDER BY c IS NULL)
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Changes to test/nulls1.test.
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
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







-
+













-
+







  2 1 11   2 2 12   2 {} 1 
  3 2 12   3 {} 1   3 {} 3
}
do_eqp_test 5.3 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST
} {
  QUERY PLAN
  `--SEARCH TABLE t4 USING INDEX t4ab (a=?)
  `--SEARCH t4 USING INDEX t4ab (a=?)
}

do_execsql_test 5.4 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST
} {
  3 {} 3   3 {} 1   3 2 12   
  2 {} 1   2 2 12   2 1 11   
  1 {} 1   1 2 12   1 1 11   
}
do_eqp_test 5.5 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST
} {
  QUERY PLAN
  `--SEARCH TABLE t4 USING INDEX t4ab (a=?)
  `--SEARCH t4 USING INDEX t4ab (a=?)
}

#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
  CREATE TABLE t5(a, b, c);
  WITH s(i) AS (
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243







-
+








-
+







  CREATE INDEX t5ab ON t5(a, b, c);
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} $res1
do_eqp_test 6.1.2 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} {
  QUERY PLAN
  `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?)
  `--SEARCH t5 USING COVERING INDEX t5ab (a=?)
}
do_execsql_test 6.2.1 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC 
} $res2
do_eqp_test 6.2.2 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC 
} {
  QUERY PLAN
  `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?)
  `--SEARCH t5 USING COVERING INDEX t5ab (a=?)
}

#-------------------------------------------------------------------------
do_execsql_test 7.0 {
  CREATE TABLE t71(a, b, c);
  CREATE INDEX t71abc ON t71(a, b, c);

290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304







-
+







  1 10 a 1 10 b 1 10 c 1 10 d 1 10 NULL 1 10 NULL
  2 10 a 2 10 b 2 10 c 2 10 d 2 10 NULL 2 10 NULL
}

do_eqp_test 9.4 {
  SELECT c1, c2, ifnull(c3, 'NULL') FROM v0 
  WHERE c2=10 ORDER BY c1, c3 NULLS LAST
} {SEARCH TABLE v0 USING COVERING INDEX v3 (ANY(c1) AND c2=?)}
} {SEARCH v0 USING COVERING INDEX v3 (ANY(c1) AND c2=?)}


# 2020-03-01 ticket e12a0ae526bb51c7
# NULLS LAST on a LEFT JOIN
#
reset_db
do_execsql_test 10.10 {
Changes to test/orderby1.test.
512
513
514
515
516
517
518
519

520
521
522
523
524
525
526
512
513
514
515
516
517
518

519
520
521
522
523
524
525
526







-
+







  CREATE INDEX i1 ON t1(a);
}

do_eqp_test 8.1 {
  SELECT * FROM t1 ORDER BY a, b;
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING INDEX i1
  |--SCAN t1 USING INDEX i1
  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_execsql_test 8.2 {
  WITH cnt(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
  )
Changes to test/permutations.test.
985
986
987
988
989
990
991
992

993
994
995
996
997
998
999
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999







-
+







  unregister_jt_vfs
} -files [test_set $::allquicktests -exclude {
  wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test 
  async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
  pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
  pager2.test *fault* rowal* snapshot* superlock* symlink.test
  delete_db.test shmlock.test chunksize.test
  busy2.test avfs.test
  busy2.test avfs.test external_reader.test
}]

if {[info commands register_demovfs] != ""} {
  test_suite "demovfs" -description {
    Check that the demovfs (code in test_demovfs.c) more or less works.
  } -initialize {
    register_demovfs
Changes to test/releasetest.tcl.
51
52
53
54
55
56
57

58
59
60
61
62
63
64
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65







+







    --disable-amalgamation --disable-shared
    --enable-session
    -DSQLITE_ENABLE_DESERIALIZE
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
    -DCONFIG_SLOWDOWN_FACTOR=5.0
    --enable-session
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {
250
251
252
253
254
255
256

257
258
259
260
261
262
263
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265







+







    -DHAVE_USLEEP=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DCONFIG_SLOWDOWN_FACTOR=8.0
    --enable-json1
  }

  # The next group of configurations are used only by the
  # Failure-Detection platform.  They are all the same, but we need
  # different names for them all so that they results appear in separate
  # subdirectories.
Changes to test/releasetest_data.tcl.
52
53
54
55
56
57
58

59
60
61
62
63
64
65
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66







+







    --disable-amalgamation --disable-shared
    --enable-session
    -DSQLITE_ENABLE_DESERIALIZE
  }
  "Sanitize" {
    CC=clang -fsanitize=address,undefined
    -DSQLITE_ENABLE_STAT4
    -DCONFIG_SLOWDOWN_FACTOR=5.0
    --enable-debug
    --enable-all
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
254
255
256
257
258
259
260

261
262
263
264
265
266
267
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269







+







    -DSQLITE_OMIT_LOOKASIDE=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DCONFIG_SLOWDOWN_FACTOR=8.0
    --enable-json1
  }

  "Windows-Memdebug" {
    MEMDEBUG=1
    DEBUG=3
  }
Changes to test/returning1.test.
111
112
113
114
115
116
117













118
119







































































































































































111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297







+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
} {123}

do_execsql_test 5.5 {
  INSERT INTO t2(b) VALUES('abc');
  UPDATE t2 SET b='123' WHERE b='abc' RETURNING (SELECT b FROM t1);
} {123}

# Ticket 132994c8b1063bfb
reset_db
do_catchsql_test 6.0 {
  CREATE TABLE t1(id INTEGER PRIMARY KEY);
  CREATE TABLE t2(x INT, y INT);
  INSERT INTO t1 VALUES(1),(2),(4),(9);
  INSERT INTO t2 VALUES(3,7), (4,25), (5,99);
  UPDATE t1 SET id=id+y FROM t2 WHERE t1.id=t2.x RETURNING t2.*;
} {1 {RETURNING may not use "TABLE.*" wildcards}}
do_catchsql_test 6.1 {
  UPDATE t1 SET id=id+y FROM t2 WHERE t1.id=t2.x RETURNING *, '|';
  SELECT * FROM t1 ORDER BY id;
} {0 {29 | 1 2 9 29}}
finish_test


# Forum https://sqlite.org/forum/forumpost/85aef8bc01
# Do not silently ignore nonsense table names in the RETURNING clause.
# Raise an error.
#
reset_db
do_execsql_test 7.1 {
  CREATE TABLE t1(a INT, b INT);
  CREATE TABLE t2(x INT, y INT);
  INSERT INTO t1(a,b) VALUES(1,2);
  INSERT INTO t2(x,y) VALUES(1,30);
} {}
do_catchsql_test 7.2 {
  UPDATE t1 SET b=b+1 RETURNING new.b;
} {1 {no such column: new.b}}
do_catchsql_test 7.3 {
  UPDATE t1 SET b=b+1 RETURNING old.b;
} {1 {no such column: old.b}}
do_catchsql_test 7.4 {
  UPDATE t1 SET b=b+1 RETURNING another.b;
} {1 {no such column: another.b}}
do_catchsql_test 7.5 {
  UPDATE t1 SET b=b+y FROM t2 WHERE t2.x=t1.a RETURNING t2.x;
} {1 {no such column: t2.x}}
do_catchsql_test 7.6 {
  UPDATE t1 SET b=b+y FROM t2 WHERE t2.x=t1.a RETURNING t1.b;
} {0 32}

# This is goofy:  The RETURNING clause does not honor the alias
# for the table being modified.  This might change in the future.
#
do_catchsql_test 7.7 {
  UPDATE t1 AS alias SET b=123 RETURNING alias.b;
} {1 {no such column: alias.b}}
do_catchsql_test 7.8 {
  UPDATE t1 AS alias SET b=alias.b+1000 RETURNING t1.b;
} {0 1032}

# Forum: https://sqlite.org/forum/info/34c81d83c9177f46
reset_db
do_execsql_test 8.1 {
  CREATE TABLE t1(a);
  CREATE TABLE t2(b,c);
  INSERT INTO t1 VALUES(1);
  INSERT INTO t2 VALUES(3,40);
} {}
do_catchsql_test 8.2 {
  INSERT INTO t1 VALUES(3) RETURNING a, (SELECT c FROM t2 WHERE new.a=t2.b) AS x;
} {1 {no such column: new.a}}
do_catchsql_test 8.3 {
  INSERT INTO t1 VALUES(3) RETURNING a, (SELECT c FROM t2 WHERE old.a=t2.b) AS x;
} {1 {no such column: old.a}}
do_catchsql_test 8.4 {
  INSERT INTO t1 VALUES(3) RETURNING a, (SELECT c FROM t2 WHERE t1.a=t2.b) AS x;
} {0 {3 40}}

ifcapable vtab {
# dbsqlfuzz finds/crash-486f791cbe2dc45839310073e71367a1d8ad22dd
do_catchsql_test 9.1 {
  UPDATE pragma_encoding SET encoding='UTF-8' RETURNING a, b, *;
} {1 {table pragma_encoding may not be modified}}
} ;# ifcapable vtab

# dbsqlfuzz crash-0081f863d7b2002045ac2361879fc80dfebb98f1
reset_db
do_execsql_test 10.1 {
  CREATE TABLE t1_a(a, b);
  CREATE VIEW t1 AS SELECT a, b FROM t1_a;

  INSERT INTO t1_a VALUES('x', 'y');
  INSERT INTO t1_a VALUES('x', 'y');
  INSERT INTO t1_a VALUES('x', 'y');

  CREATE TABLE log(op, r, a, b);
}
do_execsql_test 10.2 {
  CREATE TRIGGER tr1 INSTEAD OF INSERT ON t1 BEGIN
    INSERT INTO log VALUES('insert', new.rowid, new.a, new.b);
  END;
  CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN
    INSERT INTO log VALUES('update', new.rowid, new.a, new.b);
  END;
}

do_catchsql_test 10.3 {
  INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid;
} {1 {no such column: rowid}}

do_catchsql_test 10.3 {
  UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid;
} {1 {no such column: rowid}}

do_execsql_test 10.4 {
  SELECT * FROM log;
} {}

# 2021-04-27 dbsqlfuzz 78b9400770ef8cc7d9427dfba26f4fcf46ea7dc2
# Returning clauses on TEMP tables with triggers.
#
reset_db
do_execsql_test 11.1 {
  CREATE TEMP TABLE t1(a,b);
  CREATE TEMP TABLE t2(c,d);
  CREATE TEMP TABLE t3(e,f);
  CREATE TEMP TABLE log(op,x,y);
  CREATE TEMP TRIGGER t1r1 AFTER INSERT ON t1 BEGIN
     INSERT INTO log(op,x,y) VALUES('I1',new.a,new.b);
  END;
  CREATE TEMP TRIGGER t1r2 BEFORE DELETE ON t1 BEGIN
     INSERT INTO log(op,x,y) VALUES('D1',old.a,old.b);
  END;
  CREATE TEMP TRIGGER t2r3 AFTER UPDATE ON t1 BEGIN
     INSERT INTO log(op,x,y) VALUES('U1',new.a,new.b);
  END;
  CREATE TEMP TRIGGER t2r1 BEFORE INSERT ON t2 BEGIN
     INSERT INTO log(op,x,y) VALUES('I2',new.c,new.d);
  END;
  CREATE TEMP TRIGGER t3r1 AFTER DELETE ON t3 BEGIN
     INSERT INTO log(op,x,y) VALUES('D3',old.e,old.f);
  END;
  CREATE TEMP TRIGGER t3r2 BEFORE UPDATE ON t3 BEGIN
     INSERT INTO log(op,x,y) VALUES('U3',new.e,new.f);
  END;
  INSERT INTO t1(a,b) VALUES(1,2),('happy','glad') RETURNING a, b, '|';
} {1 2 | happy glad |}
do_execsql_test 11.2 {
  UPDATE t1 SET b=9 WHERE a=1 RETURNING a, b, 'x';
} {1 9 x}
do_execsql_test 11.3 {
  DELETE FROM t1 WHERE a<>'xray' RETURNING a, b, '@';
} {1 9 @ happy glad @}
do_execsql_test 11.4 {
  SELECT * FROM log;
  DELETE FROM log;
} {I1 1 2 I1 happy glad U1 1 9 D1 1 9 D1 happy glad}
do_execsql_test 11.5 {
  INSERT INTO t2 VALUES('bravo','charlie') RETURNING d, c, 'z';
} {charlie bravo z}
do_execsql_test 11.6 {
  SELECT * FROM log;
  DELETE FROM log;
} {I2 bravo charlie}
do_execsql_test 11.7 {
  INSERT INTO t3(e) VALUES(1),(2),(3) RETURNING 'I', e;
  UPDATE t3 SET f=e+100 RETURNING 'U', e, f;
  DELETE FROM t3 WHERE f>100 RETURNING 'D', e, f;
} {I 1 I 2 I 3 U 1 101 U 2 102 U 3 103 D 1 101 D 2 102 D 3 103}
do_execsql_test 11.6 {
  SELECT * FROM log;
  DELETE FROM log;
} {U3 1 101 U3 2 102 U3 3 103 D3 1 101 D3 2 102 D3 3 103}

reset_db
do_execsql_test 11.11 {
  CREATE TEMP TABLE t1(a,b);
  CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN SELECT 1; END;
  DELETE FROM t1 RETURNING *;
  DROP TRIGGER r1;
  INSERT INTO t1 VALUES(5,30);
} {}
do_execsql_test 11.12 {
  SELECT * FROM t1;
} {5 30}



finish_test
Changes to test/rollback2.test.
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111







-
+







}

#--------------------------------------------------------------------
# Try with some index scans
#
do_eqp_test 3.1 {
  SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
} {SCAN TABLE t1 USING INDEX i1}
} {SCAN t1 USING INDEX i1}
do_rollback_test 3.2 -setup {
  BEGIN;
    DELETE FROM t1 WHERE (i%2)==1;
} -select {
  SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h DESC;
} -result {
  40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10  8  6  4  2
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141







-
+







# Now with some index scans that feature overflow keys.
#
set leader [string repeat "abcdefghij" 70]
do_execsql_test 4.1 { UPDATE t1 SET h = $leader || h; }

do_eqp_test 4.2 {
  SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
} {SCAN TABLE t1 USING INDEX i1}
} {SCAN t1 USING INDEX i1}
do_rollback_test 4.3 -setup {
  BEGIN;
    DELETE FROM t1 WHERE (i%2)==1;
} -select {
  SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
} -result {
  2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
Changes to test/rowvalue.test.
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
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







-
+


-
+


-
+


-
+


-
+







  INSERT INTO xy VALUES(3, 3, 3);
  INSERT INTO xy VALUES(4, 4, 4);
}


foreach {tn sql res eqp} {
  1 "SELECT * FROM xy WHERE (i, j) IS (2, 2)" {2 2 2} 
    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid=?)"
    "SEARCH xy USING INTEGER PRIMARY KEY (rowid=?)"

  2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
    "SCAN TABLE xy"
    "SCAN xy"

  3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid<?)"
    "SEARCH xy USING INTEGER PRIMARY KEY (rowid<?)"

  4 "SELECT * FROM xy WHERE (i, j) > (2, 1)" {2 2 2 3 3 3 4 4 4}
    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
    "SEARCH xy USING INTEGER PRIMARY KEY (rowid>?)"

  5 "SELECT * FROM xy WHERE (i, j) > ('2', 1)" {2 2 2 3 3 3 4 4 4}
    "SEARCH TABLE xy USING INTEGER PRIMARY KEY (rowid>?)"
    "SEARCH xy USING INTEGER PRIMARY KEY (rowid>?)"

} {
  do_eqp_test 7.$tn.1 $sql $eqp
  do_execsql_test 7.$tn.2 $sql $res
}

do_execsql_test 8.0 {
Changes to test/rowvalue4.test.
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
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+








    CREATE INDEX c1ab ON c1(a, b);
    CREATE INDEX c1cd ON c1(c, d);
    ANALYZE;
  }

  do_eqp_test 3.1.1 { SELECT * FROM c1 WHERE a=1 AND c=2 } \
     {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
     {SEARCH c1 USING INDEX c1cd (c=?)}

  do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \
     {SEARCH TABLE c1 USING INDEX c1cd (c=?)}
     {SEARCH c1 USING INDEX c1cd (c=?)}

  do_eqp_test 3.1.3 { SELECT * FROM c1 WHERE a=1 AND b>'l' AND c=2 } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=? AND b>?)}
     {SEARCH c1 USING INDEX c1ab (a=? AND b>?)}

  do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
     {SEARCH TABLE c1 USING INDEX c1cd (c>?)}
     {SEARCH c1 USING INDEX c1cd (c>?)}

  do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \
     {SEARCH TABLE c1 USING INDEX c1cd ((c,d)>(?,?))}
     {SEARCH c1 USING INDEX c1cd ((c,d)>(?,?))}

  do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}
     {SEARCH c1 USING INDEX c1ab (a=?)}

}

#------------------------------------------------------------------------

do_execsql_test 5.0 {
  CREATE TABLE d1(x, y);
230
231
232
233
234
235
236
237

238
239

240
241

242
243
244
245
246
247
248
249
250
251
252

253
254
255
256

257
258
259
260

261
262
263
264

265
266
267
268

269
270
271
272
273
274
275
230
231
232
233
234
235
236

237
238

239
240

241
242
243
244
245
246
247
248
249
250
251

252
253
254
255

256
257
258
259

260
261
262
263

264
265
266
267

268
269
270
271
272
273
274
275







-
+

-
+

-
+










-
+



-
+



-
+



-
+



-
+








do_eqp_test 5.1 {
  SELECT * FROM d2 WHERE 
    (a, b) IN (SELECT x, y FROM d1) AND
    (c) IN (SELECT y FROM d1)
} {
  QUERY PLAN
  |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?)
  |--SEARCH d2 USING INDEX d2ab (a=? AND b=?)
  |--LIST SUBQUERY xxxxxx
  |  `--SCAN TABLE d1
  |  `--SCAN d1
  `--LIST SUBQUERY xxxxxx
     `--SCAN TABLE d1
     `--SCAN d1
}

do_execsql_test 6.0 {
  CREATE TABLE e1(a, b, c, d, e);
  CREATE INDEX e1ab ON e1(a, b);
  CREATE INDEX e1cde ON e1(c, d, e);
}

do_eqp_test 6.1 {
  SELECT * FROM e1 WHERE (a, b) > (?, ?)
} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)>(?,?))}
} {SEARCH e1 USING INDEX e1ab ((a,b)>(?,?))}

do_eqp_test 6.2 {
  SELECT * FROM e1 WHERE (a, b) < (?, ?)
} {SEARCH TABLE e1 USING INDEX e1ab ((a,b)<(?,?))}
} {SEARCH e1 USING INDEX e1ab ((a,b)<(?,?))}

do_eqp_test 6.3 {
  SELECT * FROM e1 WHERE c = ? AND (d, e) > (?, ?)
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}
} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)>(?,?))}

do_eqp_test 6.4 {
  SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?)
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}
} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}

do_eqp_test 6.5 {
  SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ?
} {SEARCH TABLE e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}
} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}

#-------------------------------------------------------------------------

do_execsql_test 7.1 {
  CREATE TABLE f1(a, b, c);
  CREATE INDEX f1ab ON f1(a, b);
}
Changes to test/scanstatus.test.
41
42
43
44
45
46
47
48
49


50
51
52
53
54
55
56
57
58


59
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77
78


79
80
81
82
83
84
85
86
87
88


89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161

162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

198
199

200
201
202
203
204
205
206
207

208
209

210
211
212
213
214
215
216
217
218

219
220

221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
41
42
43
44
45
46
47


48
49
50
51
52
53
54
55
56


57
58
59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
74
75
76


77
78
79
80
81
82
83
84
85
86


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131

132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198

199
200
201
202
203
204
205
206

207
208

209
210
211
212
213
214
215
216
217

218
219

220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243







-
-
+
+







-
-
+
+








-
-
+
+








-
-
+
+








-
-
+
+



















-
+







-
+







-
+







-
+







-
+












-
+







-
+







-
+







-
+



















-
+

-
+







-
+

-
+








-
+

-
+







-
+







-
+







  }

  uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
}

do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
do_scanstatus_test 1.2 {
  nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN TABLE t1}
  nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN TABLE t2}
  nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN t1}
  nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN t2}
}

do_execsql_test 1.3 {
  ANALYZE;
  SELECT count(*) FROM t1, t2;
} 6
do_scanstatus_test 1.4 {
  nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
  nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN TABLE t2}
  nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN t1}
  nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN t2}
}

do_execsql_test 1.5 { ANALYZE }
do_execsql_test 1.6 {
  SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
} 4
do_scanstatus_test 1.7 {
  nLoop 1 nVisit 2 nEst 2.0 zName t2 zExplain 
  {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
  {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN t1}
}

do_execsql_test 1.8 {
  SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
} 4

do_scanstatus_test 1.9 {
  nLoop 2 nVisit 4 nEst 2.0 zName t2 zExplain 
  {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
  {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN t1}
}

do_test 1.9 {
  sqlite3_stmt_scanstatus_reset [db version -last-stmt-ptr]
} {}

do_scanstatus_test 1.10 {
  nLoop 0 nVisit 0 nEst 2.0 zName t2 zExplain 
  {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
  {SEARCH t2 USING INTEGER PRIMARY KEY (rowid>?)}
  nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN t1}
}

#-------------------------------------------------------------------------
# Try a few different types of scans.
#
reset_db
do_execsql_test 2.1 {
  CREATE TABLE x1(i INTEGER PRIMARY KEY, j);
  INSERT INTO x1 VALUES(1, 'one');
  INSERT INTO x1 VALUES(2, 'two');
  INSERT INTO x1 VALUES(3, 'three');
  INSERT INTO x1 VALUES(4, 'four');
  CREATE INDEX x1j ON x1(j);

  SELECT * FROM x1 WHERE i=2;
} {2 two}

do_scanstatus_test 2.2 {
  nLoop 1 nVisit 1 nEst 1.0 zName x1 
  zExplain {SEARCH TABLE x1 USING INTEGER PRIMARY KEY (rowid=?)}
  zExplain {SEARCH x1 USING INTEGER PRIMARY KEY (rowid=?)}
}

do_execsql_test 2.3.1 {
  SELECT * FROM x1 WHERE j='two'
} {2 two}
do_scanstatus_test 2.3.2 {
  nLoop 1 nVisit 1 nEst 10.0 zName x1j 
  zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j=?)}
  zExplain {SEARCH x1 USING COVERING INDEX x1j (j=?)}
}

do_execsql_test 2.4.1 {
  SELECT * FROM x1 WHERE j<'two'
} {4 four 1 one 3 three}
do_scanstatus_test 2.4.2 {
  nLoop 1 nVisit 3 nEst 262144.0 zName x1j 
  zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j<?)}
  zExplain {SEARCH x1 USING COVERING INDEX x1j (j<?)}
}

do_execsql_test 2.5.1 {
  SELECT * FROM x1 WHERE j>='two'
} {2 two}
do_scanstatus_test 2.5.2 {
  nLoop 1 nVisit 1 nEst 262144.0 zName x1j 
  zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>?)}
  zExplain {SEARCH x1 USING COVERING INDEX x1j (j>?)}
}

do_execsql_test 2.6.1 {
  SELECT * FROM x1 WHERE j BETWEEN 'three' AND 'two'
} {3 three 2 two}
do_scanstatus_test 2.6.2 {
  nLoop 1 nVisit 2 nEst 16384.0 zName x1j 
  zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j<?)}
  zExplain {SEARCH x1 USING COVERING INDEX x1j (j>? AND j<?)}
}

do_execsql_test 2.7.1 {
  CREATE TABLE x2(i INTEGER, j, k);
  INSERT INTO x2 SELECT i, j, i || ' ' || j FROM x1;
  CREATE INDEX x2j ON x2(j);
  CREATE INDEX x2ij ON x2(i, j);
  SELECT * FROM x2 WHERE j BETWEEN 'three' AND 'two'
} {3 three {3 three} 2 two {2 two}}

do_scanstatus_test 2.7.2 {
  nLoop 1 nVisit 2 nEst 16384.0 zName x2j 
  zExplain {SEARCH TABLE x2 USING INDEX x2j (j>? AND j<?)}
  zExplain {SEARCH x2 USING INDEX x2j (j>? AND j<?)}
}

do_execsql_test 2.8.1 {
  SELECT * FROM x2 WHERE i=1 AND j='two'
}
do_scanstatus_test 2.8.2 {
  nLoop 1 nVisit 0 nEst 8.0 zName x2ij 
  zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
  zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}

do_execsql_test 2.9.1 {
  SELECT * FROM x2 WHERE i=5 AND j='two'
}
do_scanstatus_test 2.9.2 {
  nLoop 1 nVisit 0 nEst 8.0 zName x2ij 
  zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
  zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}

do_execsql_test 2.10.1 {
  SELECT * FROM x2 WHERE i=3 AND j='three'
} {3 three {3 three}}
do_scanstatus_test 2.10.2 {
  nLoop 1 nVisit 1 nEst 8.0 zName x2ij 
  zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
  zExplain {SEARCH x2 USING INDEX x2ij (i=? AND j=?)}
}

#-------------------------------------------------------------------------
# Try with queries that use the OR optimization.
#
do_execsql_test 3.1 {
  CREATE TABLE a1(a, b, c, d);
  CREATE INDEX a1a ON a1(a);
  CREATE INDEX a1bc ON a1(b, c);

  WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100)
  INSERT INTO a1 SELECT x, x, x, x FROM d;
}

do_execsql_test 3.2.1 {
  SELECT d FROM a1 WHERE (a=4 OR b=13)
} {4 13}
do_scanstatus_test 3.2.2 {
  nLoop 1 nVisit 1 nEst 10.0 zName a1a 
  zExplain {SEARCH TABLE a1 USING INDEX a1a (a=?)}
  zExplain {SEARCH a1 USING INDEX a1a (a=?)}
  nLoop 1 nVisit 1 nEst 10.0 zName a1bc 
  zExplain {SEARCH TABLE a1 USING INDEX a1bc (b=?)}
  zExplain {SEARCH a1 USING INDEX a1bc (b=?)}
}

do_execsql_test 3.2.1 {
  SELECT count(*) FROM a1 WHERE (a BETWEEN 4 AND 12) OR (b BETWEEN 40 AND 60)
} {30}
do_scanstatus_test 3.2.2 {
  nLoop 1 nVisit 9 nEst 16384.0 zName a1a 
  zExplain {SEARCH TABLE a1 USING INDEX a1a (a>? AND a<?)}
  zExplain {SEARCH a1 USING INDEX a1a (a>? AND a<?)}
  nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
  zExplain {SEARCH TABLE a1 USING INDEX a1bc (b>? AND b<?)}
  zExplain {SEARCH a1 USING INDEX a1bc (b>? AND b<?)}
}

do_execsql_test 3.3.1 {
  SELECT count(*) FROM a1 AS x, a1 AS y 
  WHERE (x.a BETWEEN 4 AND 12) AND (y.b BETWEEN 1 AND 10)
} {90}
do_scanstatus_test 3.2.2 {
  nLoop 1 nVisit 10 nEst 16384.0 zName a1bc 
  zExplain {SEARCH TABLE a1 AS y USING COVERING INDEX a1bc (b>? AND b<?)}
  zExplain {SEARCH y USING COVERING INDEX a1bc (b>? AND b<?)}
  nLoop 10 nVisit 90 nEst 16384.0 zName a1a
  zExplain {SEARCH TABLE a1 AS x USING COVERING INDEX a1a (a>? AND a<?)}
  zExplain {SEARCH x USING COVERING INDEX a1a (a>? AND a<?)}
}

do_execsql_test 3.4.1 {
  SELECT count(*) FROM a1 WHERE a IN (1, 5, 10, 15);
} {4}
do_scanstatus_test 3.4.2 {
  nLoop 1 nVisit 4 nEst 40.0 zName a1a 
  zExplain {SEARCH TABLE a1 USING COVERING INDEX a1a (a=?)}
  zExplain {SEARCH a1 USING COVERING INDEX a1a (a=?)}
}

do_execsql_test 3.4.1 {
  SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15);
} {4}
do_scanstatus_test 3.4.2 {
  nLoop 1 nVisit 4 nEst 4.0 zName a1
  zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)}
  zExplain {SEARCH a1 USING INTEGER PRIMARY KEY (rowid=?)}
}

#-------------------------------------------------------------------------
# Test that scanstatus() data is not available for searches performed
# by triggers.
#
# It is available for searches performed as part of FK processing, but 
262
263
264
265
266
267
268
269

270
271

272
273
274
275
276
277
278
262
263
264
265
266
267
268

269
270

271
272
273
274
275
276
277
278







-
+

-
+







  CREATE TABLE c1(y REFERENCES p1);
  INSERT INTO c1 VALUES(1), (2), (3);
  PRAGMA foreign_keys=on;
}
do_execsql_test    4.2.1 { DELETE FROM p1 WHERE x=4 }
do_scanstatus_test 4.2.2 { 
  nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1 
  zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}
  zExplain {SEARCH p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}

  nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN TABLE c1}
  nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN c1}
}

#-------------------------------------------------------------------------
# Further tests of different scan types.
#
reset_db
proc tochar {i} {
309
310
311
312
313
314
315
316

317
318

319
320
321
322
323
324
325
326

327
328
329
330
331

332
333
334
335
336
337

338
339
340
341
342
343
344
345


346
347
348
349
350
351
352

353
354

355
356
357
358
359
360
361
362


363
364
365
366
367
368

369
370

371
372
373
374
375
376
377
309
310
311
312
313
314
315

316
317

318
319
320
321
322
323
324
325

326
327
328
329
330

331
332
333
334
335
336

337
338
339
340
341
342
343


344
345
346
347
348
349
350
351

352
353

354
355
356
357
358
359
360


361
362
363
364
365
366
367

368
369

370
371
372
373
374
375
376
377







-
+

-
+







-
+




-
+





-
+






-
-
+
+






-
+

-
+






-
-
+
+





-
+

-
+







}

do_execsql_test 5.1.1 {
  SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii)
} {2}
do_scanstatus_test 5.1.2 { 
  nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
  zExplain {SCAN TABLE t1 AS ii USING COVERING INDEX t1bc}
  zExplain {SCAN ii USING COVERING INDEX t1bc}
  nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
  zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
  zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}

do_execsql_test 5.2.1 {
  SELECT count(*) FROM t1 WHERE a IN (0, 1)
} {2}
do_scanstatus_test 5.2.2 { 
  nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1
  zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
  zExplain {SEARCH t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}

do_eqp_test 5.3.1 {
  SELECT count(*) FROM t2 WHERE y = 'j';
} {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
} {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
do_execsql_test 5.3.2 {
  SELECT count(*) FROM t2 WHERE y = 'j';
} {19}
do_scanstatus_test 5.3.3 { 
  nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
  {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
  {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}

do_eqp_test 5.4.1 {
  SELECT count(*) FROM t1, t2 WHERE y = c;
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING COVERING INDEX t1bc
  `--SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
  |--SCAN t1 USING COVERING INDEX t1bc
  `--SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
}
do_execsql_test 5.4.2 {
  SELECT count(*) FROM t1, t2 WHERE y = c;
} {200}
do_scanstatus_test 5.4.3 { 
  nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
  zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
  zExplain {SCAN t1 USING COVERING INDEX t1bc}
  nLoop 10 nVisit 200 nEst 56.0 zName t2xy 
  zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
  zExplain {SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}

do_eqp_test 5.5.1 {
  SELECT count(*) FROM t1, t3 WHERE y = c;
} {
  QUERY PLAN
  |--SCAN TABLE t3
  `--SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)
  |--SCAN t3
  `--SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?)
}
do_execsql_test 5.5.2 {
  SELECT count(*) FROM t1, t3 WHERE y = c;
} {200}
do_scanstatus_test 5.5.3 { 
  nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3}
  nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN t3}
  nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain
  {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
  {SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?)}
}

#-------------------------------------------------------------------------
# Virtual table scans
#
ifcapable fts3 {
  do_execsql_test 6.0 {
388
389
390
391
392
393
394
395

396
397
398
399
400
388
389
390
391
392
393
394

395
396
397
398
399
400







-
+





    INSERT INTO ft1 VALUES('a d e f b j j c g d');
  }
  do_execsql_test 6.1.1 {
    SELECT count(*) FROM ft1 WHERE ft1 MATCH 'd'
  } {6}
  do_scanstatus_test 6.1.2 { 
    nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain 
    {SCAN TABLE ft1 VIRTUAL TABLE INDEX 3:}
    {SCAN ft1 VIRTUAL TABLE INDEX 3:}
  }
}


finish_test
Changes to test/select4.test.
1021
1022
1023
1024
1025
1026
1027














1028
1029
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043







+
+
+
+
+
+
+
+
+
+
+
+
+
+


  SELECT * FROM t1;
} {123}
do_execsql_test select4-18.3 {
  SELECT * FROM t1 AS z1 JOIN t1 AS z2 USING(aa)
   WHERE abs(z1.aa)=z2.aa AND z1.aa=123;
} {123}

# 2021-03-31 Fix an assert() problem in the logic at the end of sqlite3Select()
# that validates AggInfo.  The checks to ensure that AggInfo.aCol[].pCExpr
# references a valid expression was looking at an expression that had been
# deleted by the truth optimization in sqlite3ExprAnd() which was invoked by
# the push-down optimization.  This is harmless in delivery builds, as that code
# only runs with SQLITE_DEBUG.  But it should still be fixed.  The problem
# was discovered by dbsqlfuzz (crash-dece7b67a3552ed7e571a7bda903afd1f7bd9b21)
#
reset_db
do_execsql_test select4-19.1 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(99);
  SELECT sum((SELECT 1 FROM (SELECT 2 WHERE x IS NULL) WHERE 0)) FROM t1;
} {{}}

finish_test
Changes to test/select5.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
8
9
10
11
12
13
14

15
16
17
18
19
20
21







-







#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing aggregate functions and the
# GROUP BY and HAVING clauses of SELECT statements.
#
# $Id: select5.test,v 1.20 2008/08/21 14:15:59 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Build some test data
#
execsql {
247
248
249
250
251
252
253
254
255
256









257
246
247
248
249
250
251
252



253
254
255
256
257
258
259
260
261
262







-
-
-
+
+
+
+
+
+
+
+
+

} {two 3 one 6}
do_test select5-8.8 {
  execsql {
    SELECT a, count(*) FROM t8a, t8b GROUP BY a ORDER BY 2;
  }
} {two 3 one 9}



 
# 2021-04-26 forum https://sqlite.org/forum/forumpost/74330094d8
reset_db
do_execsql_test select5-9.1 {
  CREATE TABLE t1(a INT, b INT);
  INSERT INTO t1(a,b) VALUES(1,null),(null,null),(1,null);
  CREATE UNIQUE INDEX t1b ON t1(abs(b));
  SELECT quote(a), quote(b), '|' FROM t1 GROUP BY a, abs(b);
} {NULL NULL | 1 NULL |}

finish_test
Changes to test/select9.test.
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
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







-
+





-
+





-
+







       UNION ALL
       SELECT x, y FROM t52;
    CREATE INDEX t51x ON t51(x);
    CREATE INDEX t52x ON t52(x);
    EXPLAIN QUERY PLAN
       SELECT * FROM v5 WHERE x='12345' ORDER BY y;
  }
} {~/SCAN TABLE/}  ;# Uses indices with "*"
} {~/SCAN/}  ;# Uses indices with "*"
do_test select9-5.2 {
  db eval {
    EXPLAIN QUERY PLAN
       SELECT x, y FROM v5 WHERE x='12345' ORDER BY y;
  }
} {~/SCAN TABLE/}  ;# Uses indices with "x, y"
} {~/SCAN/}  ;# Uses indices with "x, y"
do_test select9-5.3 {
  db eval {
    EXPLAIN QUERY PLAN
       SELECT x, y FROM v5 WHERE +x='12345' ORDER BY y;
  }
} {/SCAN TABLE/}   ;# Full table scan if the "+x" prevents index usage.
} {/SCAN/}   ;# Full table scan if the "+x" prevents index usage.

# 2013-07-09:  Ticket [490a4b7235624298]: 
# "WHERE 0" on the first element of a UNION causes an assertion fault
#
do_execsql_test select9-6.1 {
  CREATE TABLE t61(a);
  CREATE TABLE t62(b);
Changes to test/selectA.test.
1335
1336
1337
1338
1339
1340
1341
1342

1343
1344
1345

1346
1347
1348
1349
1350
1351
1352
1335
1336
1337
1338
1339
1340
1341

1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1352







-
+


-
+







  UNION ALL
  SELECT a, b FROM t4 WHERE f()==f()
  ORDER BY 1,2
} {
  QUERY PLAN
  `--MERGE (UNION ALL)
     |--LEFT
     |  |--SCAN TABLE t5 USING INDEX i2
     |  |--SCAN t5 USING INDEX i2
     |  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
     `--RIGHT
        |--SCAN TABLE t4 USING INDEX i1
        |--SCAN t4 USING INDEX i1
        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_execsql_test 4.1.3 {
  SELECT c, d FROM t5 
  UNION ALL
  SELECT a, b FROM t4 WHERE f()==f()
1463
1464
1465
1466
1467
1468
1469
1470















1471
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

  SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t5) AND c1=123;
} {123 123}
do_execsql_test 7.4 {
  CREATE TABLE a(b);
  CREATE VIEW c(d) AS SELECT b FROM a ORDER BY b;
  SELECT sum(d) OVER( PARTITION BY(SELECT 0 FROM c JOIN a WHERE b =(SELECT b INTERSECT SELECT d FROM c) AND b = 123)) FROM c;
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE x1(x);
  CREATE TABLE t1(a, b, c, d);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
}

do_execsql_test 8.1 {
      SELECT 'ABCD' FROM t1 
      WHERE (a=? OR b=?) 
      AND (0 OR (SELECT 'xyz' INTERSECT SELECT a ORDER BY 1))
} {}

finish_test
Changes to test/selectD.test.
165
166
167
168
169
170
171
172

173
174
165
166
167
168
169
170
171

172
173
174







-
+


  SELECT * 
   FROM t41
   LEFT JOIN (SELECT count(*) AS cnt, x1.d
                FROM (t42 INNER JOIN t43 ON d=g) AS x1
               WHERE x1.d>5
               GROUP BY x1.d) AS x2
                  ON t41.b=x2.d;
} {/*SEARCH SUBQUERY * AS x2 USING AUTOMATIC*/}
} {/SEARCH x2 USING AUTOMATIC/}

finish_test
Changes to test/skipscan1.test.
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
337
338
339
340
341
342
343

344
345
346
347
348
349
350
351







-
+







} {/USING INDEX t9a_ab .ANY.a. AND b=./}


optimization_control db skip-scan 0
do_execsql_test skipscan1-9.3 {
  EXPLAIN QUERY PLAN
  SELECT  * FROM t9a WHERE b IN (SELECT x FROM t9b WHERE y!=5);
} {/{SCAN TABLE t9a}/}
} {/{SCAN t9a}/}
optimization_control db skip-scan 1

do_execsql_test skipscan1-2.1 {
  CREATE TABLE t6(a TEXT, b INT, c INT, d INT);
  CREATE INDEX t6abc ON t6(a,b,c);
  INSERT INTO t6 VALUES('abc',123,4,5);

390
391
392
393
394
395
396
397

398
399
400
401
402
403
404
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404







-
+







    FROM t1 WHERE t1.c3 = 1;
} {3 0 1 NULL | 0 4 1 NULL | 5 6 1 NULL |}
do_eqp_test skipscan1-3.2 {
  SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|'
    FROM t1 WHERE t1.c3 = 1;
} {
  QUERY PLAN
  |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
  |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

# 2020-01-06 ticket 304017f5f04a0035
#
reset_db
do_execsql_test skipscan1-4.10 {
Changes to test/skipscan2.test.
195
196
197
198
199
200
201
202

203
204
205
206
195
196
197
198
199
200
201

202
203
204
205
206







-
+




  for {set i 0} {$i < 1000} {incr i} {
    execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
  }
  execsql { ANALYZE }
} {}
do_eqp_test skipscan2-3.3eqp {
  SELECT * FROM t3 WHERE b=42;
} {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}
} {SEARCH t3 USING PRIMARY KEY (ANY(a) AND b=?)}



finish_test
Changes to test/skipscan5.test.
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
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







-
+


-
-
+
+




-
+


-
-
+
+







  }
  execsql ANALYZE
} {}

foreach {tn q res} {
  1  "b = 5"                   {/*ANY(a) AND b=?*/}
  2  "b > 12 AND b < 16"       {/*ANY(a) AND b>? AND b<?*/}
  3  "b > 2 AND b < 16"        {/*SCAN TABLE t1*/}
  3  "b > 2 AND b < 16"        {/*SCAN t1*/}
  4  "b > 18 AND b < 25"       {/*ANY(a) AND b>? AND b<?*/}
  5  "b > 16"                  {/*ANY(a) AND b>?*/}
  6  "b > 5"                   {/*SCAN TABLE t1*/}
  7  "b < 15"                  {/*SCAN TABLE t1*/}
  6  "b > 5"                   {/*SCAN t1*/}
  7  "b < 15"                  {/*SCAN t1*/}
  8  "b < 5"                   {/*ANY(a) AND b<?*/}
  9  "5 > b"                   {/*ANY(a) AND b<?*/}
  10 "b = '5'"                 {/*ANY(a) AND b=?*/}
  11 "b > '12' AND b < '16'"   {/*ANY(a) AND b>? AND b<?*/}
  12 "b > '2' AND b < '16'"    {/*SCAN TABLE t1*/}
  12 "b > '2' AND b < '16'"    {/*SCAN t1*/}
  13 "b > '18' AND b < '25'"   {/*ANY(a) AND b>? AND b<?*/}
  14 "b > '16'"                {/*ANY(a) AND b>?*/}
  15 "b > '5'"                 {/*SCAN TABLE t1*/}
  16 "b < '15'"                {/*SCAN TABLE t1*/}
  15 "b > '5'"                 {/*SCAN t1*/}
  16 "b < '15'"                {/*SCAN t1*/}
  17 "b < '5'"                 {/*ANY(a) AND b<?*/}
  18 "'5' > b"                 {/*ANY(a) AND b<?*/}
} {
  set sql "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE $q"
  do_execsql_test 1.3.$tn $sql $res
}

100
101
102
103
104
105
106
107

108
109
110


111
112
113
114
115
116
117
100
101
102
103
104
105
106

107
108


109
110
111
112
113
114
115
116
117







-
+

-
-
+
+







      execsql { INSERT INTO t2 VALUES($a, $b, $c, $d) }
    }
    execsql ANALYZE
  } {}

  foreach {tn2 q res} {
    1 { c BETWEEN 'd' AND 'e' }       {/*ANY(a) AND ANY(b) AND c>? AND c<?*/}
    2 { c BETWEEN 'b' AND 'r' }       {/*SCAN TABLE t2*/}
    2 { c BETWEEN 'b' AND 'r' }       {/*SCAN t2*/}
    3 { c > 'q' }                     {/*ANY(a) AND ANY(b) AND c>?*/}
    4 { c > 'e' }                     {/*SCAN TABLE t2*/}
    5 { c < 'q' }                     {/*SCAN TABLE t2*/}
    4 { c > 'e' }                     {/*SCAN t2*/}
    5 { c < 'q' }                     {/*SCAN t2*/}
    6 { c < 'b' }                     {/*ANY(a) AND ANY(b) AND c<?*/}
  } {
    set sql "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE $q" 
    do_execsql_test 2.$tn.$tn2 $sql $res
  }

}
165
166
167
168
169
170
171
172
173


174
175
176

177
178
179
180
181
182
165
166
167
168
169
170
171


172
173
174
175

176
177
178
179
180
181
182







-
-
+
+


-
+






    incr c
  }
  execsql ANALYZE
} {}

foreach {tn q res} {
  1 "b BETWEEN -10000 AND -8000"       {/*ANY(a) AND b>? AND b<?*/}
  2 "b BETWEEN -10000 AND 'qqq'"       {/*SCAN TABLE t3*/}
  3 "b < X'5555'"                      {/*SCAN TABLE t3*/}
  2 "b BETWEEN -10000 AND 'qqq'"       {/*SCAN t3*/}
  3 "b < X'5555'"                      {/*SCAN t3*/}
  4 "b > X'5555'"                      {/*ANY(a) AND b>?*/}
  5 "b > 'zzz'"                        {/*ANY(a) AND b>?*/}
  6 "b < 'zzz'"                        {/*SCAN TABLE t3*/}
  6 "b < 'zzz'"                        {/*SCAN t3*/}
} {
  set sql "EXPLAIN QUERY PLAN SELECT * FROM t3 WHERE $q" 
  do_execsql_test 3.3.$tn $sql $res
}

finish_test
Changes to test/skipscan6.test.
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189

190
191
175
176
177
178
179
180
181

182
183
184
185
186
187
188

189
190
191







-
+






-
+


  t3 t3_ba   {100 20 1 1}
}

# Use index "t3_a", as (a=?) is expected to match only a single row.
#
do_eqp_test 3.1 {
  SELECT * FROM t3 WHERE a = ? AND c = ?
} {SEARCH TABLE t3 USING INDEX t3_a (a=?)}
} {SEARCH t3 USING INDEX t3_a (a=?)}

# The same query on table t2. This should use index "t2_a", for the
# same reason. At one point though, it was mistakenly using a skip-scan.
#
do_eqp_test 3.2 {
  SELECT * FROM t2 WHERE a = ? AND c = ?
} {SEARCH TABLE t2 USING INDEX t2_a (a=?)}
} {SEARCH t2 USING INDEX t2_a (a=?)}

finish_test
Changes to test/tabfunc01.test.
222
223
224
225
226
227
228












































229
230
231
232
233
234
235
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







do_test tabfunc01-751 {
  db eval {
    SELECT aa.value, bb.value, '|'
      FROM carray(inttoptr($PTR4),5,'double') AS aa
      LEFT JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid;
  }
} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}

ifcapable altertable {
  do_test tabfunc01-800 {
    catchsql {
      ALTER TABLE generate_series ADD COLUMN col2;
    }
  } {1 {virtual tables may not be altered}}
  do_test tabfunc01-810 {
    catchsql {
      ALTER TABLE generate_series RENAME TO flubber;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-820 {
    catchsql {
      ALTER TABLE generate_series RENAME  start TO flubber;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-830 {
    catchsql {
      ALTER TABLE generate_series DROP COLUMN start;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-900 {
    catchsql {
      ALTER TABLE pragma_compile_options ADD COLUMN col2;
    }
  } {1 {virtual tables may not be altered}}
  do_test tabfunc01-910 {
    catchsql {
      ALTER TABLE pragma_compile_options RENAME TO flubber;
    }
  } {1 {table pragma_compile_options may not be altered}}
  do_test tabfunc01-920 {
    catchsql {
      ALTER TABLE pragma_compile_options RENAME  start TO flubber;
    }
  } {1 {table pragma_compile_options may not be altered}}
  do_test tabfunc01-930 {
    catchsql {
      ALTER TABLE pragma_compile_options DROP COLUMN start;
    }
  } {1 {table pragma_compile_options may not be altered}}
}


# Free up memory allocations
intarray_addr
int64array_addr
doublearray_addr
textarray_addr

Changes to test/tkt-385a5b56b9.test.
31
32
33
34
35
36
37
38

39
40
41

42
43
44

45
46
47

48
49
50
31
32
33
34
35
36
37

38
39
40

41
42
43

44
45
46

47
48
49
50







-
+


-
+


-
+


-
+



do_execsql_test 2.0 {
  CREATE TABLE t2(x, y NOT NULL);
  CREATE UNIQUE INDEX t2x ON t2(x);
  CREATE UNIQUE INDEX t2y ON t2(y);
}

do_eqp_test 2.1 { SELECT DISTINCT x FROM t2 } \
  {SCAN TABLE t2 USING COVERING INDEX t2x}
  {SCAN t2 USING COVERING INDEX t2x}

do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \
  {SCAN TABLE t2 USING COVERING INDEX t2y}
  {SCAN t2 USING COVERING INDEX t2y}

do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } \
  {SEARCH TABLE t2 USING INDEX t2y (y=?)}
  {SEARCH t2 USING INDEX t2y (y=?)}

do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \
  {SEARCH TABLE t2 USING INDEX t2x (x=?)}
  {SEARCH t2 USING INDEX t2x (x=?)}


finish_test
Changes to test/tkt-78e04e52ea.test.
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
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







-
+












-
+





-
+


do_test tkt-78e04-1.3 {
  execsql {
    CREATE INDEX i1 ON ""("" COLLATE nocase);
  }
} {}
do_test tkt-78e04-1.4 {
 db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1e5%';}
} {/*SCAN TABLE  USING COVERING INDEX i1*/}
} {/*SCAN  USING COVERING INDEX i1*/}
do_test tkt-78e04-1.5 {
  execsql {
    DROP TABLE "";
    SELECT name FROM sqlite_master;
  }
} {t2}

do_test tkt-78e04-2.1 {
  execsql {
    CREATE INDEX "" ON t2(x);
    EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=5;
  }
} {/*SEARCH TABLE t2 USING COVERING INDEX  (x=?)*/}
} {/*SEARCH t2 USING COVERING INDEX  (x=?)*/}
do_test tkt-78e04-2.2 {
  execsql {
    DROP INDEX "";
    EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2;
  }
} {/*SCAN TABLE t2*/}
} {/*SCAN t2*/}

finish_test
Changes to test/tkt-b75a9ca6b0.test.
28
29
30
31
32
33
34
35
36


37
38
39
40
41
42
43
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43







-
-
+
+







  INSERT INTO t1 VALUES (3, 1);
}

do_execsql_test 1.1 {
  CREATE INDEX i1 ON t1(x, y);
} 

set idxscan {SCAN TABLE t1 USING COVERING INDEX i1}
set tblscan {SCAN TABLE t1}
set idxscan {SCAN t1 USING COVERING INDEX i1}
set tblscan {SCAN t1}
set grpsort {USE TEMP B-TREE FOR GROUP BY}
set sort    {USE TEMP B-TREE FOR ORDER BY}

foreach {tn q res eqp} [subst -nocommands {
  1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
  {1 3  2 2  3 1} {$idxscan}

Changes to test/tkt3442.test.
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
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







-
+


-
+






-
+








# These tests perform an EXPLAIN QUERY PLAN on both versions of the 
# SELECT referenced in ticket #3442 (both '5000' and "5000") 
# and verify that the query plan is the same.
#
do_eqp_test tkt3442-1.2 {
  SELECT node FROM listhash WHERE id='5000' LIMIT 1;
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
} {SEARCH listhash USING INDEX ididx (id=?)}
do_eqp_test tkt3442-1.3 {
  SELECT node FROM listhash WHERE id="5000" LIMIT 1;
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
} {SEARCH listhash USING INDEX ididx (id=?)}


# Some extra tests testing other permutations of 5000.
#
do_eqp_test tkt3442-1.4 {
  SELECT node FROM listhash WHERE id=5000 LIMIT 1;
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
} {SEARCH listhash USING INDEX ididx (id=?)}

do_test tkt3442-1.5 {
  catchsql {
    SELECT node FROM listhash WHERE id=[5000] LIMIT 1;
  }
} {1 {no such column: 5000}}

Changes to test/tpch01.test.
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
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







-
+


-
+


-
+

















-
-
-
-
+
+
+
+





                               and p_type = 'LARGE PLATED STEEL'
               ) as all_nations
       group by
               o_year
       order by
               o_year;}]
  set ::eqpres
} {/*SEARCH TABLE part USING INDEX bootleg_pti *SEARCH TABLE lineitem USING INDEX lpki2*/}
} {/*SEARCH part USING INDEX bootleg_pti *SEARCH lineitem USING INDEX lpki2*/}
do_test tpch01-1.1b {
  set ::eqpres
} {/.* customer .* nation AS n1 .*/}
} {/.* customer .* n1 .*/}
do_test tpch01-1.1c {
  set ::eqpres
} {/.* supplier .* nation AS n2 .*/}
} {/.* supplier .* n2 .*/}

do_eqp_test tpch01-1.2 {
select
    c_custkey,    c_name,    sum(l_extendedprice * (1 - l_discount)) as revenue,
    c_acctbal,    n_name,    c_address,    c_phone,    c_comment
from
    customer,    orders,    lineitem,    nation
where
    c_custkey = o_custkey    and l_orderkey = o_orderkey
    and o_orderdate >=  '1994-08-01'    and o_orderdate < date('1994-08-01', '+3 month')
    and l_returnflag = 'R'    and c_nationkey = n_nationkey
group by
    c_custkey,    c_name,    c_acctbal,    c_phone,    n_name, c_address,    c_comment
order by
    revenue desc;
} {
  QUERY PLAN
  |--SEARCH TABLE orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)
  |--SEARCH TABLE customer USING INDEX cpki (C_CUSTKEY=?)
  |--SEARCH TABLE nation USING INDEX npki (N_NATIONKEY=?)
  |--SEARCH TABLE lineitem USING INDEX lpki (L_ORDERKEY=?)
  |--SEARCH orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)
  |--SEARCH customer USING INDEX cpki (C_CUSTKEY=?)
  |--SEARCH nation USING INDEX npki (N_NATIONKEY=?)
  |--SEARCH lineitem USING INDEX lpki (L_ORDERKEY=?)
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test
Changes to test/transitive1.test.
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354




























355
356
340
341
342
343
344
345
346

347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383







-
+






-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test transitive1-560 {
  CREATE INDEX c1x ON c1(x);
  SELECT * FROM c1 WHERE x=y AND y=z AND z='abc';
} {ABC ABC abc}
do_execsql_test transitive1-560eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM c1 WHERE x=y AND y=z AND z='abc';
} {/SCAN TABLE c1/}
} {/SCAN c1/}
do_execsql_test transitive1-570 {
  SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
} {}
do_execsql_test transitive1-570eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM c1 WHERE x=y AND z=y AND z='abc';
} {/SEARCH TABLE c1 USING INDEX c1x/}
} {/SEARCH c1 USING INDEX c1x/}

# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
reset_db
do_execsql_test transitive1-600 {
  CREATE TABLE t0(a0 INT, b1 INT);
  CREATE INDEX t0b1 ON t0(b1);
  CREATE TABLE t1(w,x,y,z3 INT);
  INSERT INTO t0(a0, b1) VALUES (0,1);
  INSERT INTO t1(w,x,y,z3) VALUES (7,8,9,1);
} {}
do_execsql_test transitive1-610 {
  SELECT ALL * FROM t0,t1 WHERE b1=z3 AND a0=z3;
} {}
do_execsql_test transitive1-620 {
  SELECT ALL * FROM t0,t1 WHERE likely(b1=z3) AND a0=z3;
} {}
do_execsql_test transitive1-630 {
  DROP TABLE t0;
  DROP TABLE t1;
  CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
  CREATE TABLE t1(c0 INT);
  INSERT INTO t0(c0, c1) VALUES (0, 1);
  INSERT INTO t1(c0) VALUES (1);
  SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (t1.c0=t0.c1);
  SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (likely(t1.c0=t0.c1));
  SELECT ALL * FROM t1,t0 WHERE (likely(t1.c0=t0.c1) AND t1.c0=t0.c0);
} {}

finish_test
Changes to test/trigger2.test.
45
46
47
48
49
50
51

52
53
54
55
56
57
58
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59







+







# trigger2-6.2[a-f]: UPDATE statements
#
# 7. & 8. Triggers on views fire correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix trigger2
ifcapable {!trigger} {
  finish_test
  return
}

# The tests in this file were written before SQLite supported recursive
# trigger invocation, and some tests depend on that to pass. So disable
765
766
767
768
769
770
771









772








773

774

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







+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+

+

+
  END;
  INSERT INTO v2(a,d) VALUES(11,14);
  SELECT * FROM t1;
} {11 {} {} 14}
 
} ;# ifcapable view

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.1 {
  CREATE TABLE t1(a INT PRIMARY KEY, b, c REAL, d, e);
  CREATE TABLE t2(a INT, b, c REAL, d, e, PRIMARY KEY(a,b)) WITHOUT ROWID;
  CREATE UNIQUE INDEX t2c ON t2(c);
  CREATE UNIQUE INDEX t2d ON t2(d);
  CREATE UNIQUE INDEX t2e ON t2(e);
}
integrity_check trigger2-999

do_catchsql_test 11.2 {
  CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN
    INSERT INTO t2(a,b,c,d,e) VALUES(91,NULL,93,94,?1)
      ON CONFLICT(b,a) DO NOTHING
      ON CONFLICT DO UPDATE SET b=?1;
  END;
} {1 {trigger cannot use variables}}


finish_test

Changes to test/trigger9.test.
238
239
240
241
242
243
244
245

246
247

248
249

250
251
252

253
254
255
256
238
239
240
241
242
243
244

245
246

247
248

249
250


251


252
253







-
+

-
+

-
+

-
-
+
-
-


  END;

  CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN
    INSERT INTO log VALUES('insert');
  END;
}

do_execsql_test 4.2 {
do_catchsql_test 4.2 {
  DELETE FROM v1 WHERE rowid=1;
} {}
} {1 {no such column: rowid}}

do_execsql_test 4.3 {
do_catchsql_test 4.3 {
  UPDATE v1 SET a=b WHERE rowid=2;
} {}

} {1 {no such column: rowid}}



finish_test
Changes to test/triggerupfrom.test.
167
168
169
170
171
172
173
174
167
168
169
170
171
172
173








-
  (2,two)->(twelve,two)
  (4,four)->(fourteen,four)
}



finish_test

Changes to test/unionall.test.
351
352
353
354
355
356
357









358
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367







+
+
+
+
+
+
+
+
+

  )
  SELECT * FROM t5, x, y;
} {
  9 10 1000 100     9 10 1000 400
  9 10 800 100      9 10 800 400
}

# 2021-04-26 dbsqlfuzz 88ed5c66789fced139d148aed823cba7c0926dd7
reset_db
do_execsql_test 7.1 {
  WITH c1(x) AS (VALUES(0) UNION ALL SELECT 100+x FROM c1 WHERE x<100 UNION ALL SELECT 1+x FROM c1 WHERE x<1)
  SELECT x, y, '|'
    FROM c1 AS x1, (SELECT x+1 AS y FROM c1 WHERE x<1 UNION ALL SELECT 1+x FROM c1 WHERE 1<x) AS x2
   ORDER BY x, y;
} {0 1 | 0 101 | 0 102 | 1 1 | 1 101 | 1 102 | 100 1 | 100 101 | 100 102 | 101 1 | 101 101 | 101 102 |}

finish_test
Changes to test/unionall2.test.
30
31
32
33
34
35
36



















37
38
39
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



    UNION ALL
    SELECT * FROM v1, v2
}

do_execsql_test 1.1 {
  SELECT 1 FROM vA, vA, vA, vA, vA, vA, vA, vA, vA, vA
}

#-------------------------------------------------------------------------

do_execsql_test 2.1 {
  CREATE TABLE y1(a INTEGER, b);
  CREATE TABLE y2(c INTEGER, d);

  CREATE TABLE x3_a(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE x3_b(c INTEGER PRIMARY KEY, d TEXT);
}

do_execsql_test 2.2 {

  SELECT * FROM y1 CROSS JOIN y2 WHERE y1.a=y2.c AND y2.c IN (
    SELECT a FROM x3_a UNION ALL
    SELECT c FROM x3_b ORDER BY 1
  )
}



finish_test
Changes to test/unordered.test.
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
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







-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+


-
-
+
+

-
-
+
+






  if {$idxmode == "unordered"} {
    execsql { UPDATE sqlite_stat1 SET stat = stat || ' unordered' }
  }
  db close
  sqlite3 db test.db
  foreach {tn sql r(ordered) r(unordered)} {
    1   "SELECT * FROM t1 ORDER BY a"
        {SCAN TABLE t1 USING INDEX i1}
        {SCAN TABLE t1*USE TEMP B-TREE FOR ORDER BY}
        {SCAN t1 USING INDEX i1}
        {SCAN t1*USE TEMP B-TREE FOR ORDER BY}
    2   "SELECT * FROM t1 WHERE a > 100"
        {SEARCH TABLE t1 USING INDEX i1 (a>?)}
        {SCAN TABLE t1}
        {SEARCH t1 USING INDEX i1 (a>?)}
        {SCAN t1}
    3   "SELECT * FROM t1 WHERE a = ? ORDER BY rowid"
        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
        {SEARCH TABLE t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
        {SEARCH t1 USING INDEX i1 (a=?)}
        {SEARCH t1 USING INDEX i1 (a=?)*USE TEMP B-TREE FOR ORDER BY}
    4   "SELECT max(a) FROM t1"
        {SEARCH TABLE t1 USING COVERING INDEX i1}
        {SEARCH TABLE t1}
        {SEARCH t1 USING COVERING INDEX i1}
        {SEARCH t1}
    5   "SELECT group_concat(b) FROM t1 GROUP BY a"
        {SCAN TABLE t1 USING INDEX i1}
        {SCAN TABLE t1*USE TEMP B-TREE FOR GROUP BY}
        {SCAN t1 USING INDEX i1}
        {SCAN t1*USE TEMP B-TREE FOR GROUP BY}

    6   "SELECT * FROM t1 WHERE a = ?"
        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
        {SEARCH t1 USING INDEX i1 (a=?)}
        {SEARCH t1 USING INDEX i1 (a=?)}
    7   "SELECT count(*) FROM t1"
        {SCAN TABLE t1 USING COVERING INDEX i1}
        {SCAN TABLE t1}
        {SCAN t1 USING COVERING INDEX i1}
        {SCAN t1}
  } {
    do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
  }
}

finish_test
Changes to test/upfrom2.test.
363
364
365
366
367
368
369
370
371
363
364
365
366
367
368
369









-
-
} {
  do_catchsql_test 5.$tn $update \
    "1 {target object/alias may not appear in FROM clause: $nm}"
}


finish_test


Changes to test/upfrom3.test.
255
256
257
258
259
260
261
262
255
256
257
258
259
260
261








-
      SELECT * FROM c1
    } {a 1  b 12  c 112}

  }]
}

finish_test

Changes to test/upfromfault.test.
133
134
135
136
137
138
139
140
133
134
135
136
137
138
139








-
      error "unexpected result: $res"
    }
  }
}


finish_test

Changes to test/walsetlk.test.
191
192
193
194
195
196
197
198
191
192
193
194
195
196
197








-
} {wal}

do_test 3.1 {
  list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}

finish_test

Changes to test/where.test.
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
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







-
+


-
+











-
+





-
+







  count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3}
do_test where-1.1.1b {
  count {SELECT x, y, w FROM t1 WHERE w IS 10}
} {3 121 10 3}
do_eqp_test where-1.1.2 {
  SELECT x, y, w FROM t1 WHERE w=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.1.2b {
  SELECT x, y, w FROM t1 WHERE w IS 10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.1.3 {
  db status step
} {0}
do_test where-1.1.4 {
  db eval {SELECT x, y, w FROM t1 WHERE +w=10}
} {3 121 10}
do_test where-1.1.5 {
  db status step
} {99}
do_eqp_test where-1.1.6 {
  SELECT x, y, w FROM t1 WHERE +w=10
} {*SCAN TABLE t1*}
} {*SCAN t1*}
do_test where-1.1.7 {
  count {SELECT x, y, w AS abc FROM t1 WHERE abc=10}
} {3 121 10 3}
do_eqp_test where-1.1.8 {
  SELECT x, y, w AS abc FROM t1 WHERE abc=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.1.9 {
  db status step
} {0}
do_test where-1.2.1 {
  count {SELECT x, y, w FROM t1 WHERE w=11}
} {3 144 11 3}
do_test where-1.2.2 {
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
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







-
+


-
+





-
+





-
+











-
+


-
+







  count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3}
do_test where-1.4.1b {
  count {SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2}
} {11 3 144 3}
do_eqp_test where-1.4.2 {
  SELECT w, x, y FROM t1 WHERE 11=w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.4.2b {
  SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.4.3 {
  count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3}
do_eqp_test where-1.4.4 {
  SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.5 {
  count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_eqp_test where-1.5.2 {
  SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?)*}
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_test where-1.6 {
  count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
do_test where-1.7 {
  count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
} {3 144 3}
do_test where-1.8 {
  count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
} {3 144 3}
do_eqp_test where-1.8.2 {
  SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3
} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*}
} {*SEARCH t1 USING INDEX i1xy (x=? AND y=?)*}
do_eqp_test where-1.8.3 {
  SELECT x, y FROM t1 WHERE y=144 AND x=3
} {*SEARCH TABLE t1 USING COVERING INDEX i1xy (x=? AND y=?)*}
} {*SEARCH t1 USING COVERING INDEX i1xy (x=? AND y=?)*}
do_test where-1.9 {
  count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
do_test where-1.10 {
  count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
} {3 121 3}
do_test where-1.11 {
Changes to test/where2.test.
72
73
74
75
76
77
78


79
80


81
82

83
84
85
86
87
88
89
72
73
74
75
76
77
78
79
80


81
82
83

84
85
86
87
88
89
90
91







+
+
-
-
+
+

-
+







  set ::sqlite_sort_count 0
  set data [execsql $sql]
  if {$::sqlite_sort_count} {set x sort} {set x nosort}
  lappend data $x
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  # puts eqp=$eqp
  foreach {a b c x} $eqp {
    if {[regexp {SCAN CONSTANT} $x]} {
      # noop
    if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}


749
750
751
752
753
754
755
756

757
758
759
760
761
762
763
751
752
753
754
755
756
757

758
759
760
761
762
763
764
765







-
+







do_execsql_test where2-12.1 {
  CREATE TABLE t12(x INTEGER PRIMARY KEY, y INT, z CHAR(100));
  CREATE INDEX t12y ON t12(y);
  EXPLAIN QUERY PLAN
    SELECT a.x, b.x
      FROM t12 AS a JOIN t12 AS b ON a.y=b.x
     WHERE (b.x=$abc OR b.y=$abc);
} {/.*SEARCH TABLE t12 AS b .*SEARCH TABLE t12 AS b .*/}
} {/SEARCH b .*SEARCH b /}
}

# Verify that all necessary OP_OpenRead opcodes occur in the OR optimization.
#
do_execsql_test where2-13.1 {
  CREATE TABLE t13(a,b);
  CREATE INDEX t13a ON t13(a);
Changes to test/where3.test.
107
108
109
110
111
112
113


114
115


116
117

118
119
120
121
122
123
124
107
108
109
110
111
112
113
114
115


116
117
118

119
120
121
122
123
124
125
126







+
+
-
-
+
+

-
+







#
proc queryplan {sql} {
  set ::sqlite_sort_count 0
  set data [execsql $sql]
  set eqp [execsql "EXPLAIN QUERY PLAN $sql"]
  # puts eqp=$eqp
  foreach {a b c x} $eqp {
    if {[regexp {SCAN CONSTANT} $x]} {
      # noop
    if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}


236
237
238
239
240
241
242
243
244


245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274



275
276
277
278
279
280
281
282



283
284
285
286
287
288
289
290



291
292
293
294
295
296
297
238
239
240
241
242
243
244


245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273



274
275
276
277
278
279
280
281



282
283
284
285
286
287
288
289



290
291
292
293
294
295
296
297
298
299







-
-
+
+





-
-
+
+




















-
-
-
+
+
+





-
-
-
+
+
+





-
-
-
+
+
+







  INSERT INTO t302 VALUES(4,5);
  ANALYZE;
}
do_eqp_test where3-3.0a {
  SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
} {
  QUERY PLAN
  |--SCAN TABLE t302
  `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t302
  `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test where3-3.1 {
  SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y;
} {
  QUERY PLAN
  |--SCAN TABLE t302
  `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SCAN t302
  `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
}
do_execsql_test where3-3.2 {
  SELECT * FROM t301 WHERE c=3 AND a IS NULL;
} {}
do_execsql_test where3-3.3 {
  SELECT * FROM t301 WHERE c=3 AND a IS NOT NULL;
} {1 2 3 2 2 3}

if 0 {  # Query planner no longer does this
# Verify that when there are multiple tables in a join which must be
# full table scans that the query planner attempts put the table with
# the fewest number of output rows as the outer loop.
#
do_execsql_test where3-4.0 {
  CREATE TABLE t400(a INTEGER PRIMARY KEY, b, c);
  CREATE TABLE t401(p INTEGER PRIMARY KEY, q, r);
  CREATE TABLE t402(x INTEGER PRIMARY KEY, y, z);
  EXPLAIN QUERY PLAN
  SELECT * FROM t400, t401, t402 WHERE t402.z GLOB 'abc*';
} {
  0 0 2 {SCAN TABLE t402} 
  0 1 0 {SCAN TABLE t400} 
  0 2 1 {SCAN TABLE t401}
  0 0 2 {SCAN t402} 
  0 1 0 {SCAN t400} 
  0 2 1 {SCAN t401}
}
do_execsql_test where3-4.1 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t400, t401, t402 WHERE t401.r GLOB 'abc*';
} {
  0 0 1 {SCAN TABLE t401} 
  0 1 0 {SCAN TABLE t400} 
  0 2 2 {SCAN TABLE t402}
  0 0 1 {SCAN t401} 
  0 1 0 {SCAN t400} 
  0 2 2 {SCAN t402}
}
do_execsql_test where3-4.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t400, t401, t402 WHERE t400.c GLOB 'abc*';
} {
  0 0 0 {SCAN TABLE t400} 
  0 1 1 {SCAN TABLE t401} 
  0 2 2 {SCAN TABLE t402}
  0 0 0 {SCAN t400} 
  0 1 1 {SCAN t401} 
  0 2 2 {SCAN t402}
}
} ;# endif

# Verify that a performance regression encountered by firefox
# has been fixed.
#
do_execsql_test where3-5.0 {
317
318
319
320
321
322
323
324
325


326
327
328
329
330
331
332
333
334
335
336
337
338


339
340
341
342
343
344
345
346
347
348
349
350
351


352
353
354
355
356
357
358
359
360
361
362
363
364


365
366
367
368
369
370
371
319
320
321
322
323
324
325


326
327
328
329
330
331
332
333
334
335
336
337
338


339
340
341
342
343
344
345
346
347
348
349
350
351


352
353
354
355
356
357
358
359
360
361
362
363
364


365
366
367
368
369
370
371
372
373







-
-
+
+











-
-
+
+











-
-
+
+











-
-
+
+







     FROM aaa JOIN bbb ON bbb.id = aaa.parent  
    WHERE aaa.fk = 'constant'
      AND LENGTH(bbb.title) > 0
      AND bbb.parent = 4
    ORDER BY bbb.title COLLATE NOCASE ASC;
} {
  QUERY PLAN
  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.1 {
   SELECT bbb.title AS tag_title 
     FROM aaa JOIN aaa AS bbb ON bbb.id = aaa.parent  
    WHERE aaa.fk = 'constant'
      AND LENGTH(bbb.title) > 0
      AND bbb.parent = 4
    ORDER BY bbb.title COLLATE NOCASE ASC;
} {
  QUERY PLAN
  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.2 {
   SELECT bbb.title AS tag_title 
     FROM bbb JOIN aaa ON bbb.id = aaa.parent  
    WHERE aaa.fk = 'constant'
      AND LENGTH(bbb.title) > 0
      AND bbb.parent = 4
    ORDER BY bbb.title COLLATE NOCASE ASC;
} {
  QUERY PLAN
  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH TABLE bbb USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}
do_eqp_test where3-5.3 {
   SELECT bbb.title AS tag_title 
     FROM aaa AS bbb JOIN aaa ON bbb.id = aaa.parent  
    WHERE aaa.fk = 'constant'
      AND LENGTH(bbb.title) > 0
      AND bbb.parent = 4
    ORDER BY bbb.title COLLATE NOCASE ASC;
} {
  QUERY PLAN
  |--SEARCH TABLE aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH TABLE aaa AS bbb USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

# Name resolution with NATURAL JOIN and USING
#
do_test where3-6.setup {
  db eval {
Changes to test/where7.test.
23350
23351
23352
23353
23354
23355
23356
23357

23358
23359
23360


23361
23362
23363
23364
23350
23351
23352
23353
23354
23355
23356

23357
23358


23359
23360
23361
23362
23363
23364







-
+

-
-
+
+




      AND (t301.c4 = 1407449685622784
           OR t301.c8 = 1407424651264000)
   ORDER BY t302.c5 LIMIT 200;
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t301 USING COVERING INDEX t301_c4 (c4=?)
  |  |  `--SEARCH t301 USING COVERING INDEX t301_c4 (c4=?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
  |     `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test
Changes to test/where9.test.
358
359
360
361
362
363
364
365

366
367
368

369
370

371
372
373
374
375
376
377
378

379
380
381

382
383

384
385
386
387
388
389
390
358
359
360
361
362
363
364

365
366
367

368
369

370
371
372
373
374
375
376
377

378
379
380

381
382

383
384
385
386
387
388
389
390







-
+


-
+

-
+







-
+


-
+

-
+








ifcapable explain {
  do_eqp_test where9-3.1 {
    SELECT t2.a FROM t1, t2
    WHERE t1.a=80 AND ((t1.c=t2.c AND t1.d=t2.d) OR t1.f=t2.f)
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
    |--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2d (d=?)
       |  `--SEARCH t2 USING INDEX t2d (d=?)
       `--INDEX 3
          `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
          `--SEARCH t2 USING COVERING INDEX t2f (f=?)
  }]
  do_eqp_test where9-3.2 {
    SELECT coalesce(t2.a,9999)
    FROM t1 LEFT JOIN t2 ON (t1.c+1=t2.c AND t1.d=t2.d) OR (t1.f||'x')=t2.f
    WHERE t1.a=80
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
    |--SEARCH t1 USING INTEGER PRIMARY KEY (rowid=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2d (d=?)
       |  `--SEARCH t2 USING INDEX t2d (d=?)
       `--INDEX 2
          `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
          `--SEARCH t2 USING COVERING INDEX t2f (f=?)
  }]
} 

# Make sure that INDEXED BY and multi-index OR clauses play well with
# one another.
#
do_test where9-4.1 {
457
458
459
460
461
462
463
464

465
466

467
468
469
470
471
472
473

474
475
476
477
478
479
480

481
482
483
484
485
486
487
457
458
459
460
461
462
463

464
465

466
467
468
469
470
471
472

473
474
475
476
477
478
479

480
481
482
483
484
485
486
487







-
+

-
+






-
+






-
+







#
do_eqp_test where9-5.1 {
  SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t1 USING INDEX t1c (c=?)
     |  `--SEARCH t1 USING INDEX t1c (c=?)
     `--INDEX 2
        `--SEARCH TABLE t1 USING INDEX t1d (d=?)
        `--SEARCH t1 USING INDEX t1d (d=?)
}

# In contrast, b=1000 is preferred over any OR-clause.
#
do_eqp_test where9-5.2 {
  SELECT a FROM t1 WHERE b=1000 AND (c=31031 OR d IS NULL)
} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
} {SEARCH t1 USING INDEX t1b (b=?)}

# Likewise, inequalities in an AND are preferred over inequalities in
# an OR.
#
do_eqp_test where9-5.3 {
  SELECT a FROM t1 WHERE b>1000 AND (c>=31031 OR d IS NULL)
} {SEARCH TABLE t1 USING INDEX t1b (b>?)}
} {SEARCH t1 USING INDEX t1b (b>?)}

############################################################################
# Make sure OR-clauses work correctly on UPDATE and DELETE statements.

do_test where9-6.2.1 {
  db eval {SELECT count(*) FROM t1 UNION ALL SELECT a FROM t1 WHERE a>=85}
} {99 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99}
Changes to test/whereE.test.
43
44
45
46
47
48
49
50

51
52
53

54
55
56
57

58
59
60

61
62
43
44
45
46
47
48
49

50
51
52

53
54
55
56

57
58
59

60
61
62







-
+


-
+



-
+


-
+


  INSERT INTO t2 SELECT x+32, (x+32)*11 FROM t2;
  INSERT INTO t2 SELECT x+64, (x+32)*11 FROM t2;
  ALTER TABLE t2 ADD COLUMN z;
  UPDATE t2 SET z=2;
  CREATE UNIQUE INDEX t2zx ON t2(z,x);

  EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.2 {
  EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.3 {
  ANALYZE;
  EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.4 {
  EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
} {/.*SCAN t1.*SEARCH t2.*/}

finish_test
Changes to test/whereF.test.
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
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







-
+




















-
+







foreach {tn sql} {
  1 "SELECT * FROM t1,           t2 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10"
  2 "SELECT * FROM t2,           t1 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10"
  3 "SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10"
} {
  do_test 1.$tn {
    db eval "EXPLAIN QUERY PLAN $sql"
   } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
   } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}

do_execsql_test 2.0 {
  DROP TABLE t1;
  DROP TABLE t2;
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);

  CREATE UNIQUE INDEX i1 ON t1(a);
  CREATE UNIQUE INDEX i2 ON t1(b);
  CREATE UNIQUE INDEX i3 ON t2(d);
} {}

foreach {tn sql} {
  1 "SELECT * FROM t1,           t2 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e"
  2 "SELECT * FROM t2,           t1 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e"
  3 "SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e"
} {
  do_test 2.$tn {
    db eval "EXPLAIN QUERY PLAN $sql"
   } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
   } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}

do_execsql_test 3.0 {
  DROP TABLE t1;
  DROP TABLE t2;
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);
105
106
107
108
109
110
111
112

113
114
115
116
117
118
119
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119







-
+







     WHERE t2.d=t1.b AND t1.a=(t2.d+1) AND t1.b = (t2.e+1)}

  3 {SELECT t1.a, t1.b, t2.d, t2.e FROM t2 CROSS JOIN t1 
     WHERE t2.d=t1.b AND t1.a=(t2.d+1) AND t1.b = (t2.e+1)}
} {
  do_test 3.$tn {
    db eval "EXPLAIN QUERY PLAN $sql"
   } {/.*SCAN TABLE t2\y.*SEARCH TABLE t1\y.*/}
   } {/.*SCAN t2\y.*SEARCH t1\y.*/}
}

do_execsql_test 4.0 {
  CREATE TABLE t4(a,b,c,d,e, PRIMARY KEY(a,b,c));
  CREATE INDEX t4adc ON t4(a,d,c);
  CREATE UNIQUE INDEX t4aebc ON t4(a,e,b,c);
  EXPLAIN QUERY PLAN SELECT rowid FROM t4 WHERE a=? AND b=?;
Changes to test/whereG.test.
152
153
154
155
156
157
158
159

160
161
162

163
164
165

166
167
168

169
170
171
172
173
174
175
152
153
154
155
156
157
158

159
160
161

162
163
164

165
166
167

168
169
170
171
172
173
174
175







-
+


-
+


-
+


-
+







#
do_execsql_test whereG-3.0 {
  CREATE TABLE a(a1 PRIMARY KEY, a2);
  CREATE TABLE b(b1 PRIMARY KEY, b2);
} {}
do_eqp_test whereG-3.1 {
  SELECT * FROM a, b WHERE b1=a1 AND a2=5;
} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.2 {
  SELECT * FROM a, b WHERE a1=b1 AND a2=5;
} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.3 {
  SELECT * FROM a, b WHERE a2=5 AND b1=a1;
} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}
do_eqp_test whereG-3.4 {
  SELECT * FROM a, b WHERE a2=5 AND a1=b1;
} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
} {/.*SCAN a.*SEARCH b USING INDEX .*b_1 .b1=..*/}

# Ticket [1e64dd782a126f48d78c43a664844a41d0e6334e]:
# Incorrect result in a nested GROUP BY/DISTINCT due to the use of an OP_SCopy
# where an OP_Copy was needed.
#
do_execsql_test whereG-4.0 {
  CREATE TABLE t4(x);
191
192
193
194
195
196
197
198

199
200
201

202
203
204

205
206
207
208
209
210
211
212
213
214
215

216
217
218

219
220
221

222
223
224
225
226

227
228
229
230

231
232
233
234

235
236
237

238
239
240
241
242
243
244
191
192
193
194
195
196
197

198
199
200

201
202
203

204
205
206
207
208
209
210
211
212
213
214

215
216
217

218
219
220

221
222
223
224
225

226
227
228
229

230
231
232
233

234
235
236

237
238
239
240
241
242
243
244







-
+


-
+


-
+










-
+


-
+


-
+




-
+



-
+



-
+


-
+








do_execsql_test 5.1 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX i1 ON t1(a, b);
}
do_eqp_test 5.1.2 {
  SELECT * FROM t1 WHERE a>?
} {SEARCH TABLE t1 USING INDEX i1 (a>?)}
} {SEARCH t1 USING INDEX i1 (a>?)}
do_eqp_test 5.1.3 {
  SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test 5.1.4 {
  SELECT * FROM t1 WHERE likely(a>?)
} {SCAN TABLE t1}
} {SCAN t1}

do_test 5.2 {
  for {set i 0} {$i < 100} {incr i} {
    execsql { INSERT INTO t1 VALUES('abc', $i, $i); }
  }
  execsql { INSERT INTO t1 SELECT 'def', b, c FROM t1; }
  execsql { ANALYZE }
} {}
do_eqp_test 5.2.2 {
  SELECT * FROM t1 WHERE likelihood(b>?, 0.01)
} {SEARCH TABLE t1 USING INDEX i1 (ANY(a) AND b>?)}
} {SEARCH t1 USING INDEX i1 (ANY(a) AND b>?)}
do_eqp_test 5.2.3 {
  SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test 5.2.4 {
  SELECT * FROM t1 WHERE likely(b>?)
} {SCAN TABLE t1}
} {SCAN t1}

ifcapable stat4 {
  do_eqp_test 5.3.1.stat4 {
    SELECT * FROM t1 WHERE a=?
  } {SCAN TABLE t1}
  } {SCAN t1}
} else {
  do_eqp_test 5.3.1 {
    SELECT * FROM t1 WHERE a=?
  } {SEARCH TABLE t1 USING INDEX i1}
  } {SEARCH t1 USING INDEX i1}
}
do_eqp_test 5.3.2 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
} {SCAN TABLE t1}
} {SCAN t1}
do_eqp_test 5.3.3 {
  SELECT * FROM t1 WHERE likely(a=?)
} {SCAN TABLE t1}
} {SCAN t1}

# 2015-06-18
# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
#
do_execsql_test 6.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(i int, x, y, z);
329
330
331
332
333
334
335
336

































337
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

reset_db
do_execsql_test 10.1 {
  CREATE TABLE a(b TEXT);  INSERT INTO a VALUES(0),(4),(9);
  CREATE TABLE c(d NUM);
  CREATE VIEW f(g, h) AS SELECT b, 0 FROM a UNION SELECT d, d FROM c;
  SELECT g = g FROM f GROUP BY h;
} {1}

reset_db
do_execsql_test 11.0 {
  CREATE TABLE t1(x PRIMARY KEY, y);
  INSERT INTO t1 VALUES('AAA', 'BBB');

  CREATE TABLE t2(z);
  INSERT INTO t2 VALUES('t2');

  CREATE TABLE t3(x PRIMARY KEY, y);
  INSERT INTO t3 VALUES('AAA', 'AAA');
}

do_execsql_test 11.1.1 {
  SELECT * FROM t1 JOIN t2 ON unlikely(x=y) AND y='AAA'
}
do_execsql_test 11.1.2 {
  SELECT * FROM t1 JOIN t2 ON likely(x=y) AND y='AAA'
}
do_execsql_test 11.1.3 {
  SELECT * FROM t1 JOIN t2 ON x=y AND y='AAA'
}

do_execsql_test 11.2.1 {
  SELECT * FROM t3 JOIN t2 ON unlikely(x=y) AND y='AAA'
} {AAA AAA t2}
do_execsql_test 11.2.2 {
  SELECT * FROM t3 JOIN t2 ON likely(x=y) AND y='AAA'
} {AAA AAA t2}
do_execsql_test 11.2.3 {
  SELECT * FROM t3 JOIN t2 ON x=y AND y='AAA'
} {AAA AAA t2}


finish_test
Changes to test/whereI.test.
28
29
30
31
32
33
34
35

36
37

38
39
40
41
42
43
44
28
29
30
31
32
33
34

35
36

37
38
39
40
41
42
43
44







-
+

-
+








do_eqp_test 1.1 {
  SELECT a FROM t1 WHERE b='b' OR c='x'
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t1 USING INDEX i1 (b=?)
     |  `--SEARCH t1 USING INDEX i1 (b=?)
     `--INDEX 2
        `--SEARCH TABLE t1 USING INDEX i2 (c=?)
        `--SEARCH t1 USING INDEX i2 (c=?)
}

do_execsql_test 1.2 {
  SELECT a FROM t1 WHERE b='b' OR c='x'
} {2 3}

do_execsql_test 1.3 {
60
61
62
63
64
65
66
67

68
69

70
71
72
73
74
75
76
60
61
62
63
64
65
66

67
68

69
70
71
72
73
74
75
76







-
+

-
+








do_eqp_test 2.1 {
  SELECT a FROM t2 WHERE b='b' OR c='x'
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t2 USING INDEX i3 (b=?)
     |  `--SEARCH t2 USING INDEX i3 (b=?)
     `--INDEX 2
        `--SEARCH TABLE t2 USING INDEX i4 (c=?)
        `--SEARCH t2 USING INDEX i4 (c=?)
}

do_execsql_test 2.2 {
  SELECT a FROM t2 WHERE b='b' OR c='x'
} {ii iii}

do_execsql_test 2.3 {
Changes to test/whereJ.test.
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
398
399
400
401
402
403
404

405
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420







-
+







-
+








# This one should use index "idx_c".
do_eqp_test 3.4 {
  SELECT * FROM t1 WHERE 
    a = 4 AND b BETWEEN 20 AND 80           -- Matches 80 rows
      AND
    c BETWEEN 150 AND 160                   -- Matches 10 rows
} {SEARCH TABLE t1 USING INDEX idx_c (c>? AND c<?)}
} {SEARCH t1 USING INDEX idx_c (c>? AND c<?)}

# This one should use index "idx_ab".
do_eqp_test 3.5 {
  SELECT * FROM t1 WHERE 
    a = 5 AND b BETWEEN 20 AND 80           -- Matches 1 row
      AND
    c BETWEEN 150 AND 160                   -- Matches 10 rows
} {SEARCH TABLE t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}
} {SEARCH t1 USING INDEX idx_ab (a=? AND b>? AND b<?)}

###########################################################################################

# Reset the database and setup for a test case derived from actual SQLite users
#
db close
sqlite3 db test.db
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643







-
+







     px
  WHERE
     cx.code = '2990'
     AND cx.type=2
     AND px.cx_id = cx.cx_id
     AND px.px_tid = 0
     AND px.le_id = le.le_id;
} {/.*SCAN TABLE cx.*SEARCH TABLE px.*SEARCH TABLE le.*/}
} {/.*SCAN cx.*SEARCH px.*SEARCH le.*/}


# The following test is derived from a performance problem reported from
# the field.  Notice the multiple indexes with the same initial tables,
# and the unusual WHERE clause terms.
#
do_test 5.1 {
Changes to test/whereK.test.
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
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







-
+







-
+







-
+







-
+









-
+


    INSERT INTO t1(a,b,c) SELECT x, x/10, x%10 FROM c;
  CREATE INDEX t1bc ON t1(b,c);
  SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
} {90 91 92 93 94 95 96 97 98 99}
do_execsql_test 1.1eqp {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a;
} {/SEARCH TABLE t1 USING INDEX t1bc/}
} {/SEARCH t1 USING INDEX t1bc/}

do_execsql_test 1.2 {
  SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
} {88 89 90 91 92 93 94 95 96 97 98 99}
do_execsql_test 1.2eqp {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a;
} {/SEARCH TABLE t1 USING INDEX t1bc/}
} {/SEARCH t1 USING INDEX t1bc/}

do_execsql_test 1.3 {
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
} {88 89 90 91 92 93 94 95 96 97 98 99}
do_execsql_test 1.3eqp {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a;
} {/SEARCH TABLE t1 USING INDEX t1bc/}
} {/SEARCH t1 USING INDEX t1bc/}

do_execsql_test 1.4 {
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
} {88 89 90 91 92 93 94 95 96 97 98 99}
do_execsql_test 1.4eqp {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR 8<b ORDER BY +a;
} {/SEARCH TABLE t1 USING INDEX t1bc/}
} {/SEARCH t1 USING INDEX t1bc/}

do_execsql_test 1.5 {
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
   ORDER BY +a;
} {88 89 90 91 92 93 97 98 99}
do_execsql_test 1.5eqp {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6))
   ORDER BY +a;
} {/SEARCH TABLE t1 USING INDEX t1bc/}
} {/SEARCH t1 USING INDEX t1bc/}

finish_test
Changes to test/whereL.test.
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
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







-
-
+
+

-
-
+
+












-
-
-
+
+
+







}
do_eqp_test 110 {
  SELECT * FROM t1, v4 WHERE t1.a=?1 AND v4.a=t1.a;
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
     |  `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
     |  |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
     |  `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
     `--UNION ALL
        |--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
        `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
        |--SEARCH t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
        `--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
}

# The scan of the t1 table goes first since that enables the ORDER BY
# sort to be omitted.  This would not be possible without constant
# propagation because without it the t1 table would depend on t3.
#
do_eqp_test 120 {
  SELECT * FROM t1, t2, t3
   WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=5
  ORDER BY t1.a;
} {
  QUERY PLAN
  |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
  |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
  `--SCAN TABLE t3
  |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
  |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
  `--SCAN t3
}

# Constant propagation in the face of collating sequences:
#
do_execsql_test 200 {
  CREATE TABLE c3(x COLLATE binary, y COLLATE nocase, z COLLATE binary);
  CREATE INDEX c3x ON c3(x);
Changes to test/wherefault.test.
51
52
53
54
55
56
57
























58
59
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


    set iii [expr $i*$i]
    db eval { INSERT INTO t1 VALUES($i, $ii, $iii) }
  }
  db eval COMMIT
} -sqlbody {
  SELECT count(*) FROM t1 WHERE a BETWEEN 5 AND 995 OR b BETWEEN 5 AND 900000;
}

reset_db
do_execsql_test 3.0 {
  PRAGMA writable_schema = 1;
  BEGIN TRANSACTION;    
    CREATE TABLE t1(
      a INT AS (c*11),
      b TEXT AS (substr(d,1,3)) STORED, 
      c INTEGEB PRIMARI KEY, d TEXT
    );
    CREATE INDEX t1a ON t1(a);
  COMMIT;
}
faultsim_save_and_close

do_faultsim_test 3.1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT b FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT CASE b WHEN 82 THEN 207 WHEN 869 THEN 406 WHEN 85 THEN 83 WHEN 705 THEN 698 ELSE 1992229051 END%5 FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT b FROM t1 ORDER BY b) WHERE a IN (SELECT b FROM t1 ORDER BY b))) WHERE a );
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test
Changes to test/wherelimit.test.
233
234
235
236
237
238
239
240
241


242
243
244
245
246
247
248
233
234
235
236
237
238
239


240
241
242
243
244
245
246
247
248







-
-
+
+







  } {36}
  do_test wherelimit-3.1 {
    execsql {UPDATE t1 SET y=1 WHERE x=1}
    execsql {SELECT count(*) FROM t1 WHERE y=1}
  } {11}
  create_test_data 6
  do_test wherelimit-3.2 {
    execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, old.y, '|' LIMIT 5}
  } {1 1 | 1 2 | 1 3 | 1 4 | 1 5 |}
    execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, y, '|' LIMIT 5}
  } {1 1 | 1 1 | 1 1 | 1 1 | 1 1 |}
  do_test wherelimit-3.2cnt {
    execsql {SELECT count(*) FROM t1 WHERE y=1}
  } {10}
  do_test wherelimit-3.3 {
    # limit 5
    execsql {UPDATE t1 SET y=2 WHERE x=2 ORDER BY x LIMIT 5}
    execsql {SELECT count(*) FROM t1 WHERE y=2}
Changes to test/window1.test.
370
371
372
373
374
375
376
































377
378
379
380
381
382
383
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  WITH aaa(x, y, z) AS (
    SELECT x, y, max(y) OVER xyz FROM t4
    WINDOW xyz AS (ORDER BY x)
  )
  SELECT *, min(z) OVER (ORDER BY x) FROM aaa ORDER BY 1;
} {1 g g g   2 i i g   3 l l g   4 g l g   5 a l g   6 m m g}

do_catchsql_test 9.4 {
  -- 2021-04-17 dbsqlfuzz d9cf66100064952b66951845dfab41de1c124611
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,c,d);
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(x,y);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2(x,y)
      SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (PARTITION BY EXISTS(SELECT 1 FROM t1 WHERE c=?1) );
  END;
} {1 {trigger cannot use variables}}

do_catchsql_test 9.4.2 {
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t1(a,b) 
        SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (
          ORDER BY a ROWS BETWEEN ? PRECEDING AND UNBOUNDED FOLLOWING
        );
  END;
} {1 {trigger cannot use variables}}
do_catchsql_test 9.4.3 {
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t1(a,b) 
        SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (
          ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND ? FOLLOWING
        );
  END;
} {1 {trigger cannot use variables}}

#-------------------------------------------------------------------------
#
do_execsql_test 10.0 {
  CREATE TABLE sales(emp TEXT PRIMARY KEY, region, total);
  INSERT INTO sales VALUES
      ('Alice',     'North', 34),
      ('Frank',     'South', 22),
1996
1997
1998
1999
2000
2001
2002
2003



























































2004
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
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095








+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 65.4 {
  SELECT COUNT() OVER () LIKE lead(102030) OVER(
      ORDER BY sum('abcdef' COLLATE nocase) IN (SELECT 54321) 
  )
  FROM t1;
} {{}}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 66.1 {
  CREATE TABLE t1(a INTEGER);
  INSERT INTO t1 VALUES(3578824042033200656);
  INSERT INTO t1 VALUES(3029012920382354029);
}

foreach {tn spec} {
  1 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
  2 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 0.1 PRECEDING"
  3 "ORDER BY a RANGE BETWEEN 0.3 FOLLOWING AND 10 FOLLOWING"
  4 "ORDER BY a DESC RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
  5 "ORDER BY a NULLS LAST RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"
  6 "ORDER BY a RANGE BETWEEN 1.0 PRECEDING AND 2.0 PRECEDING"
} {
  do_execsql_test 66.2.$tn "
    SELECT total(a) OVER ( $spec ) FROM t1 ORDER BY a
  " {
    3.02901292038235e+18 3.5788240420332e+18
  }
}


do_execsql_test 66.3 {
  CREATE TABLE t2(a INTEGER);
  INSERT INTO t2 VALUES(45);
  INSERT INTO t2 VALUES(30);
}

foreach {tn spec res} {
  1 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING"   {30.0 45.0}
  2 "ORDER BY a RANGE BETWEEN 0.3 PRECEDING AND 0.1 PRECEDING"  {0.0 0.0}
  3 "ORDER BY a RANGE BETWEEN 0.3 FOLLOWING AND 10 FOLLOWING"   {0.0 0.0}
  4 "ORDER BY a DESC RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING" {30.0 45.0}
  5 "ORDER BY a NULLS LAST RANGE BETWEEN 0.3 PRECEDING AND 10 FOLLOWING" {30.0 45.0}
  6 "ORDER BY a RANGE BETWEEN 1.0 PRECEDING AND 2.0 PRECEDING" {0.0 0.0}
} {
  do_execsql_test 66.2.$tn "
    SELECT total(a) OVER ( $spec ) FROM t2 ORDER BY a
  " $res
}


#-------------------------------------------------------------------------
reset_db
do_execsql_test 67.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(a, b, c);
}

do_catchsql_test 67.1 {
  SELECT a,c,b FROM t1 INTERSECT SELECT a,b,c FROM t1 ORDER BY (             
      SELECT nth_value(a,2) OVER w1 
      WINDOW w1 AS ( ORDER BY ((SELECT 1 FROM v1)) )
  )
} {1 {1st ORDER BY term does not match any column in the result set}}

finish_test
Changes to test/window9.test.
260
261
262
263
264
265
266

















267
268
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


do_execsql_test 8.4 {
  SELECT(
      SELECT x UNION 
      SELECT sum( avg((SELECT x FROM v1)) ) OVER()
  )
  FROM v1;
} {0.0 0.0}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(NULL,'bb',356);
  INSERT INTO t1 VALUES('CB','aa',158);
  INSERT INTO t1 VALUES('BB','aa',399);
  INSERT INTO t1 VALUES('FF','bb',938);
}

do_catchsql_test 9.1 {
  SELECT sum(c) OVER (
    ORDER BY c RANGE BETWEEN 0 PRECEDING AND '-700' PRECEDING
  )
  FROM t1
} {1 {frame ending offset must be a non-negative number}}

finish_test
Changes to test/windowfault.test.
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
280
281
282
283
284
285
286

287
288
289
290
291
292
293
294







-
+







do_execsql_test 12.0 {
  CREATE TABLE t1(a, b, c);
} {}
do_faultsim_test 12 -faults oom* -prep {
} -body {
  execsql {
    WITH v(a, b, row_number) AS (
      SELECT a, b, row_number() OVER (PARTITION BY a ORDER BY b) FROM t1
      SELECT a, b, row_number() OVER (PARTITION BY a COLLATE nocase ORDER BY b) FROM t1
    )
    SELECT * FROM v WHERE a=2
  }
} -test {
  faultsim_test_result {0 {}}
}

Changes to test/windowpushd.test.
47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







-
+







  SELECT * FROM lll WHERE grp_id=2
} {
  1 2 1 2 2 11 3 2 14 4 2 16 5 2 18 6 2 20 
}

do_eqp_test 1.4 {
  SELECT * FROM lll WHERE grp_id=2
} {SEARCH TABLE t1 USING COVERING INDEX i1 (grp_id=?)}
} {SEARCH t1 USING COVERING INDEX i1 (grp_id=?)}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c, d);
  INSERT INTO t1 VALUES('A', 'C', 1,  0.1);
  INSERT INTO t1 VALUES('A', 'D', 2,  0.2);
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
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







-
+


-
+










-
+







    C 0.1 1.0 1 C 0.4 1.0 2 C 0.7 1.0 3 C 1.0 1.0 4 
    D 0.2 1.1 1 D 0.5 1.1 2 D 0.8 1.1 3 D 1.1 1.1 4 
  }

  if {$tn==1} {
    do_eqp_test 2.$tn.3.3 {
      SELECT * FROM v3 WHERE b='E'
    } {SEARCH TABLE t1 USING INDEX i2 (b=?)}
    } {SEARCH t1 USING INDEX i2 (b=?)}
    do_eqp_test 2.$tn.3.4 {
      SELECT * FROM v3 WHERE b>'C'
    } {SEARCH TABLE t1 USING INDEX i2 (b>?)}
    } {SEARCH t1 USING INDEX i2 (b>?)}
  }

  do_execsql_test 2.$tn.3.5 { SELECT * FROM v3 WHERE d<0.55; } { 
    C 0.1 1.0 1 C 0.4 1.0 2
    D 0.2 1.1 1 D 0.5 1.1 2
    E 0.3 1.2 1
  }
  if {$tn==1} {
    do_eqp_test 2.$tn.3.6 {
      SELECT * FROM v3 WHERE d<0.55
    } {SCAN TABLE t1 USING INDEX i2}
    } {SCAN t1 USING INDEX i2}
  }

  do_execsql_test 2.$tn.4.1 {
    SELECT * FROM (
      SELECT x, sum(y) AS s, max(z) AS m 
      FROM t2 GROUP BY x
    )
230
231
232
233
234
235
236
237
230
231
232
233
234
235
236








-

}




finish_test

Changes to test/with1.test.
1021
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1021
1022
1023
1024
1025
1026
1027

1028
1029


1030
1031
1032
1033
1034
1035
1036
1037
1038







-
+

-
-
+
+







  WITH
    x1(a) AS (values(100))
  INSERT INTO t1(x)
    SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  SELECT * FROM t1;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE x1
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN SUBQUERY xxxxxx
  |--SCAN x1
  `--SCAN x1
}

# 2017-10-28.
# See check-in https://sqlite.org/src/info/0926df095faf72c2
# Tried to optimize co-routine processing by changing a Copy opcode
# into SCopy.  But OSSFuzz found two (similar) cases where that optimization
# does not work.
Changes to test/with3.test.
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
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







-
+



-
-
-
+
+
+







-
+



-
-
-
+
+
+















-
+



-
+

-
-
-
-
-
+
+
+
+
+







  }

  do_eqp_test 3.1.2 {
    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
    SELECT * FROM cnt, y1 WHERE i=a
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--MATERIALIZE xxxxxx
    |--MATERIALIZE cnt
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--SCAN TABLE cnt
    |--SCAN SUBQUERY xxxxxx
    `--SEARCH TABLE y1 USING INDEX y1a (a=?)
    |     `--SCAN cnt
    |--SCAN cnt
    `--SEARCH y1 USING INDEX y1a (a=?)
  }]

  do_eqp_test 3.1.3 {
    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
    SELECT * FROM cnt, y1 WHERE i=a
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--MATERIALIZE xxxxxx
    |--MATERIALIZE cnt
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--SCAN TABLE cnt
    |--SCAN TABLE y1
    `--SEARCH SUBQUERY xxxxxx USING AUTOMATIC COVERING INDEX (i=?)
    |     `--SCAN cnt
    |--SCAN y1
    `--SEARCH cnt USING AUTOMATIC COVERING INDEX (i=?)
  }]
}

do_execsql_test 3.2.1 {
  CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
  CREATE TABLE w2(pk INTEGER PRIMARY KEY);
}

do_eqp_test 3.2.2 {
  WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
     UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
     SELECT * FROM c, w2, w1
     WHERE c.id=w2.pk AND c.id=w1.pk;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  |--SETUP
  |  |  |--SCAN CONSTANT ROW
  |  |  `--SCALAR SUBQUERY xxxxxx
  |  |     `--SCAN TABLE w2
  |  |     `--SCAN w2
  |  `--RECURSIVE STEP
  |     |--SCAN TABLE w1
  |     `--SCAN TABLE c
  |--SCAN SUBQUERY xxxxxx
  |--SEARCH TABLE w2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH TABLE w1 USING INTEGER PRIMARY KEY (rowid=?)
  |     |--SCAN w1
  |     `--SCAN c
  |--SCAN c
  |--SEARCH w2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH w1 USING INTEGER PRIMARY KEY (rowid=?)
}

do_execsql_test 4.0 {
  WITH t5(t5col1) AS (
    SELECT (
      WITH t3(t3col1) AS (
        WITH t2 AS (
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218





219
220
221
222
223
224
225
203
204
205
206
207
208
209

210
211
212
213





214
215
216
217
218
219
220
221
222
223
224
225







-
+



-
-
-
-
-
+
+
+
+
+







#
do_eqp_test 5.1 {
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
  SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
  ORDER BY 1;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  |--SETUP
  |  |  `--SCAN CONSTANT ROW
  |  `--RECURSIVE STEP
  |     `--SCAN TABLE c
  |--SCAN SUBQUERY xxxxxx AS x1
  |--SCAN SUBQUERY xxxxxx AS x2
  |--SCAN SUBQUERY xxxxxx AS x3
  |--SCAN SUBQUERY xxxxxx AS x4
  |     `--SCAN c
  |--SCAN x1
  |--SCAN x2
  |--SCAN x3
  |--SCAN x4
  `--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 5.2 {
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
  SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
  ORDER BY 1;
} {0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111}
Changes to test/with6.test.
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
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







-
+

-
-
-
+
+
+











-
+

-
-
-
+
+
+














-
+

-
-
-
+
+
+

















-
-
+
+

-
-
-
+
+
+

-
-
-
+
+
+

-
-
-
-
+
+
+
+







  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 101 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

do_execsql_test 110 {
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 111 {
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

# Even though the CTE is not materialized, the self-join optimization
# kicks in and does the materialization for us.
#
do_execsql_test 120 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 121 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

do_execsql_test 130 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 5) AS c2,
         (SELECT x FROM c LIMIT 5) AS c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 131 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 5) AS c2,
         (SELECT x FROM c LIMIT 5) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |--MATERIALIZE c1
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |  `--SCAN c
  |--MATERIALIZE c2
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |  `--SCAN c
  |--MATERIALIZE c3
  |  |--CO-ROUTINE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |  `--SCAN c
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

# The (SELECT x FROM c LIMIT N) subqueries get materialized once each.
# Show multiple materializations are shown.  But there is only one
# materialization for c, shown by the "SCAN 2 CONSTANT ROWS" line.
#
do_execsql_test 140 {
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
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







-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

















-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+













-
+

-
+

-
+













-
+

-
+

-
+

-
+







  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |  `--SCAN c
  |--MATERIALIZE c2
  |  `--SCAN c
  |--MATERIALIZE c3
  |  `--SCAN c
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

do_execsql_test 150 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 151 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
  |  `--SCAN c
  |--MATERIALIZE c2
  |  `--SCAN c
  |--MATERIALIZE c3
  |  `--SCAN c
  |--SCAN c1
  |--SCAN c2
  `--SCAN c3
}

do_execsql_test 160 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {100 301}
do_eqp_test 161 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c2
  |--SCAN c2
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     `--SCAN SUBQUERY xxxxxx
     `--SCAN c
}

do_execsql_test 170 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {100 301}
do_eqp_test 171 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {
  QUERY PLAN
  |--CO-ROUTINE xxxxxx
  |--CO-ROUTINE c
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c2
  |--SCAN c2
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     |--CO-ROUTINE xxxxxx
     |--CO-ROUTINE c
     |  `--SCAN 2 CONSTANT ROWS
     `--SCAN SUBQUERY xxxxxx
     `--SCAN c
}


do_execsql_test 200 {
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES(4);
  CREATE VIEW t2(y) AS
224
225
226
227
228
229
230
231
232


233
234
235
236
237
238
239






240
241
242
243
244
245
246
224
225
226
227
228
229
230


231
232
233






234
235
236
237
238
239
240
241
242
243
244
245
246







-
-
+
+

-
-
-
-
-
-
+
+
+
+
+
+







           (SELECT z FROM c LIMIT 5) AS c2;
  SELECT y FROM t2 ORDER BY y;
} {40404 40405 40406 40504 40505 40506 40604 40605 40606}
do_eqp_test 211 {
  SELECT y FROM t2 ORDER BY y;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |--MATERIALIZE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 3 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  |--SCAN TABLE t1
  |  `--SCAN c
  |--MATERIALIZE c2
  |  `--SCAN c
  |--SCAN c1
  |--SCAN c2
  |--SCAN t1
  `--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 220 {
  DROP VIEW t2;
  CREATE VIEW t2(y) AS
    WITH c(z) AS MATERIALIZED (VALUES(4),(5),(6))
    SELECT c1.z+c2.z*100+t1.x*10000
Changes to test/without_rowid6.test.
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
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







-
+


















-
+

















-
+



















-
+










} {4 1}
do_execsql_test_if_vtab without_rowid6-201 {
  SELECT name, key FROM pragma_index_xinfo('t1');
} {b 1 a 0 c 0}
do_execsql_test without_rowid6-210 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-220 {
  PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}

do_execsql_test without_rowid6-300 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(
    a UNIQUE,
    b PRIMARY KEY,
    c UNIQUE,
    UNIQUE(b)
  ) WITHOUT ROWID;
  INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {4 1}
do_execsql_test without_rowid6-310 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-320 {
  PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}

do_execsql_test without_rowid6-400 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(
    a UNIQUE,
    b UNIQUE PRIMARY KEY,
    c UNIQUE
  ) WITHOUT ROWID;
  INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {4 1}
do_execsql_test without_rowid6-410 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-420 {
  PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_2 1 pk/}

do_execsql_test without_rowid6-500 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,c,
    UNIQUE(b,c),
    PRIMARY KEY(b,c)
  ) WITHOUT ROWID;
  INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9);
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {4 1}
do_execsql_test_if_vtab without_rowid6-501 {
  SELECT name, key FROM pragma_index_xinfo('t1');
} {b 1 c 1 a 0}
do_execsql_test without_rowid6-510 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../}
} {/SEARCH t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-520 {
  PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_1 1 pk/}

do_catchsql_test without_rowid6-600 {
  CREATE TABLE t6(a,b,c,PRIMARY KEY(a,rowid,b))WITHOUT ROWID;
} {1 {no such column: rowid}}


finish_test
Changes to test/zipfile.test.
838
839
840
841
842
843
844












845
846
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858







+
+
+
+
+
+
+
+
+
+
+
+


#
do_catchsql_test 16.10 {
  DELETE FROM zipfile;
} {1 {zipfile: missing filename}}
do_catchsql_test 16.20 {
  REPLACE INTO zipfile VALUES(null,null,null,null,null,123,null);
} {1 {zipfile: missing filename}}

# 2021-04-22 forum https://sqlite.org/forum/forumpost/d82289d69f
do_execsql_test 17.1 {
  WITH vlist(x) AS (
     VALUES(9223372036854775807),
           (-9223372036854775808),
           (9223372036854775806),
           (-9223372036854775807)
  )
  SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist;
} {blob}
  

finish_test
Changes to tool/lemon.c.
2704
2705
2706
2707
2708
2709
2710
2711

2712
2713
2714
2715
2716
2717
2718
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2718







-
+







      }
      break;
    case WAITING_FOR_TOKEN_NAME:
      /* Tokens do not have to be declared before use.  But they can be
      ** in order to control their assigned integer number.  The number for
      ** each token is assigned when it is first seen.  So by including
      **
      **     %token ONE TWO THREE
      **     %token ONE TWO THREE.
      **
      ** early in the grammar file, that assigns small consecutive values
      ** to each of the tokens ONE TWO and THREE.
      */
      if( x[0]=='.' ){
        psp->state = WAITING_FOR_DECL_OR_RULE;
      }else if( !ISUPPER(x[0]) ){
Changes to tool/omittest.tcl.
250
251
252
253
254
255
256

257
258
259
260
261
262
263
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264







+







    SQLITE_OMIT_WAL \
    SQLITE_OMIT_WINDOWFUNC \
    SQLITE_OMIT_WSD \
    SQLITE_OMIT_XFER_OPT \
  ]

  set ::ENABLE_SYMBOLS [list \
    SQLITE_ALLOW_ROWID_IN_VIEW \
    SQLITE_DISABLE_DIRSYNC \
    SQLITE_DISABLE_LFS \
    SQLITE_ENABLE_ATOMIC_WRITE \
    SQLITE_ENABLE_COLUMN_METADATA \
    SQLITE_ENABLE_EXPENSIVE_ASSERT \
    SQLITE_ENABLE_FTS3 \
    SQLITE_ENABLE_FTS3_PARENTHESIS \
Changes to tool/showdb.c.
908
909
910
911
912
913
914

915
916
917
918










919
920
921
922
923
924
925
908
909
910
911
912
913
914
915
916
917


918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934







+


-
-
+
+
+
+
+
+
+
+
+
+







  }else{
    page_usage_msg(pgno, "orphaned %s, %s", zType, zEntry);
  }
  if( a[hdr]==2 || a[hdr]==5 ){
    int cellstart = hdr+12;
    u32 child;
    for(i=0; i<nCell; i++){
      u32 cellidx;
      u32 ofst;

      ofst = cellstart + i*2;
      ofst = a[ofst]*256 + a[ofst+1];
      cellidx = cellstart + i*2;
      if( cellidx+1 >= g.pagesize ){
        printf("ERROR: page %d too many cells (%d)\n", pgno, nCell);
        break;
      }
      ofst = a[cellidx]*256 + a[cellidx+1];
      if( ofst<cellidx+2 || ofst+4>=g.pagesize ){
        printf("ERROR: page %d cell %d out of bounds\n", pgno, i);
        continue;
      }
      child = decodeInt32(a+ofst);
      page_usage_btree(child, pgno, i, zName);
    }
    child = decodeInt32(a+cellstart-4);
    page_usage_btree(child, pgno, i, zName);
  }
  if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){